blob: 555d66527a704d1f6dca1a34678c0d654cd47a01 [file] [log] [blame]
/*
* Copyright 2017 HugeGraph Authors
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package com.baidu.hugegraph.unit.license;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;
import java.util.prefs.Preferences;
import javax.security.auth.x500.X500Principal;
import org.apache.commons.codec.Charsets;
import org.apache.commons.io.FileUtils;
import org.junit.After;
import org.junit.Test;
import com.baidu.hugegraph.license.CommonLicenseManager;
import com.baidu.hugegraph.license.ExtraParam;
import com.baidu.hugegraph.license.FileKeyStoreParam;
import com.baidu.hugegraph.license.LicenseCreateParam;
import com.baidu.hugegraph.license.LicenseVerifyParam;
import com.baidu.hugegraph.testutil.Assert;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import de.schlichtherle.license.CipherParam;
import de.schlichtherle.license.DefaultCipherParam;
import de.schlichtherle.license.DefaultLicenseParam;
import de.schlichtherle.license.KeyStoreParam;
import de.schlichtherle.license.LicenseContent;
import de.schlichtherle.license.LicenseContentException;
import de.schlichtherle.license.LicenseManager;
import de.schlichtherle.license.LicenseParam;
import de.schlichtherle.license.NoLicenseInstalledException;
public class LicenseManagerTest {
private static final Charset CHARSET = Charsets.UTF_8;
private static final ObjectMapper MAPPER = new ObjectMapper();
@After
public void teardown() throws IOException {
File lic = new File("src/test/resources/hugegraph-evaluation.license");
FileUtils.forceDelete(lic);
}
@Test
public void testCreateInstallVerifyLicense() throws IOException {
String createConfigPath = "src/test/resources/create-license.json";
LicenseCreator creator = LicenseCreator.build(createConfigPath);
creator.create();
String verifyConfigPath = "src/test/resources/verify-license.json";
LicenseVerifier verifier = LicenseVerifier.build(verifyConfigPath);
verifier.install();
verifier.verify();
}
@Test
public void testCreateVerifyLicenseWithoutInstall() throws IOException {
String createConfigPath = "src/test/resources/create-license.json";
LicenseCreator creator = LicenseCreator.build(createConfigPath);
creator.create();
String verifyConfigPath = "src/test/resources/verify-license.json";
LicenseVerifier verifier = LicenseVerifier.build(verifyConfigPath);
verifier.uninstall();
Assert.assertThrows(RuntimeException.class, () -> {
verifier.verify();
}, e -> {
Assert.assertEquals(NoLicenseInstalledException.class,
e.getCause().getClass());
});
}
private static class LicenseCreator {
private static final X500Principal DEFAULT_ISSUER = new X500Principal(
"CN=localhost, OU=localhost, O=localhost, L=SH, ST=SH, C=CN");
private final LicenseCreateParam param;
public LicenseCreator(LicenseCreateParam param) {
this.param = param;
}
public static LicenseCreator build(String path) throws IOException {
File file = FileUtils.getFile(path);
String json;
try {
json = FileUtils.readFileToString(file, CHARSET);
} catch (IOException e) {
throw new RuntimeException(String.format(
"Failed to read file '%s'", path));
}
LicenseCreateParam param = MAPPER.readValue(
json, LicenseCreateParam.class);
return new LicenseCreator(param);
}
public void create(){
try {
LicenseParam licenseParam = this.initLicenseParam();
LicenseManager manager = new LicenseCreateManager(licenseParam);
LicenseContent licenseContent = this.initLicenseContent();
File licenseFile = new File(this.param.licensePath());
manager.store(licenseContent, licenseFile);
} catch (Exception e){
throw new RuntimeException("Generate license failed", e);
}
}
private LicenseParam initLicenseParam(){
Preferences preferences = Preferences.userNodeForPackage(
LicenseCreator.class);
CipherParam cipherParam = new DefaultCipherParam(
this.param.storePassword());
KeyStoreParam keyStoreParam;
keyStoreParam = new FileKeyStoreParam(LicenseCreator.class,
this.param.privateKeyPath(),
this.param.privateAlias(),
this.param.storePassword(),
this.param.keyPassword());
return new DefaultLicenseParam(this.param.subject(), preferences,
keyStoreParam, cipherParam);
}
private LicenseContent initLicenseContent(){
LicenseContent content = new LicenseContent();
content.setHolder(DEFAULT_ISSUER);
content.setIssuer(DEFAULT_ISSUER);
content.setSubject(this.param.subject());
content.setIssued(this.param.issuedTime());
content.setNotBefore(this.param.notBefore());
content.setNotAfter(this.param.notAfter());
content.setConsumerType(this.param.consumerType());
content.setConsumerAmount(this.param.consumerAmount());
content.setInfo(this.param.description());
// Customized verification params
String json;
try {
json = MAPPER.writeValueAsString(this.param.extraParams());
} catch (JsonProcessingException e) {
throw new RuntimeException("Failed to write extra params", e);
}
content.setExtra(json);
return content;
}
}
private static class LicenseCreateManager extends CommonLicenseManager {
public LicenseCreateManager(LicenseParam param) {
super(param);
}
@Override
protected synchronized void validateCreate(LicenseContent content)
throws LicenseContentException {
super.validateCreate(content);
}
}
private static class LicenseVerifier {
private final LicenseVerifyParam param;
private final LicenseVerifyManager manager;
public LicenseVerifier(LicenseVerifyParam param) {
this.param = param;
LicenseParam licenseParam = this.initLicenseParam(param);
this.manager = new LicenseVerifyManager(licenseParam);
}
public static LicenseVerifier build(String path) throws IOException {
File file = FileUtils.getFile(path);
String json;
try {
json = FileUtils.readFileToString(file, CHARSET);
} catch (IOException e) {
throw new RuntimeException(String.format(
"Failed to read file '%s'", path));
}
LicenseVerifyParam param = MAPPER.readValue(
json, LicenseVerifyParam.class);
return new LicenseVerifier(param);
}
public synchronized void install() {
try {
this.manager.uninstall();
File licenseFile = new File(this.param.licensePath());
this.manager.install(licenseFile);
} catch (Exception e) {
throw new RuntimeException("Failed to install license", e);
}
}
public synchronized void uninstall() {
try {
this.manager.uninstall();
} catch (Exception e) {
throw new RuntimeException("Failed to uninstall license", e);
}
}
public void verify() {
try {
this.manager.verify();
} catch (Exception e) {
throw new RuntimeException("The license verify failed", e);
}
}
private LicenseParam initLicenseParam(LicenseVerifyParam param) {
Preferences preferences = Preferences.userNodeForPackage(
LicenseVerifier.class);
CipherParam cipherParam = new DefaultCipherParam(
param.storePassword());
KeyStoreParam keyStoreParam = new FileKeyStoreParam(
LicenseVerifier.class,
param.publicKeyPath(),
param.publicAlias(),
param.storePassword(),
null);
return new DefaultLicenseParam(param.subject(), preferences,
keyStoreParam, cipherParam);
}
}
private static class LicenseVerifyManager extends CommonLicenseManager {
private final String serverId = "server-1";
public LicenseVerifyManager(LicenseParam param) {
super(param);
}
@Override
protected synchronized void validate(LicenseContent content)
throws LicenseContentException {
// Call super validate firstly, will verify expired
super.validate(content);
// Verify the customized license parameters
String extra = (String) content.getExtra();
List<ExtraParam> extraParams;
try {
TypeReference<List<ExtraParam>> type;
type = new TypeReference<List<ExtraParam>>() {};
extraParams = MAPPER.readValue(extra, type);
} catch (IOException e) {
throw new RuntimeException("Failed to read extra params", e);
}
ExtraParam param = this.matchParam(this.serverId, extraParams);
if (param == null) {
throw newLicenseException("The current server's id '%s' " +
"is not authorized");
}
if (this.usingGraphs() > param.graphs()) {
throw newLicenseException("The using graphs exceeded '%s'" +
"authorized limit '%s'",
this.usingGraphs(), param.graphs());
}
}
private int usingGraphs() {
// Assume
return 2;
}
private ExtraParam matchParam(String id, List<ExtraParam> extraParams) {
for (ExtraParam param : extraParams) {
if (param.id().equals(id)) {
return param;
}
}
return null;
}
private LicenseContentException newLicenseException(String message,
Object... args) {
return new LicenseContentException(String.format(message, args));
}
}
}