package io.cattle.platform.docker.machine.launch; import static io.cattle.platform.core.model.tables.SettingTable.*; import io.cattle.platform.archaius.util.ArchaiusUtil; import io.cattle.platform.core.model.Credential; import io.cattle.platform.core.model.Setting; import io.cattle.platform.iaas.api.auth.SecurityConstants; import io.cattle.platform.iaas.api.auth.integration.external.ServiceAuthConstants; import io.cattle.platform.lock.definition.LockDefinition; import io.cattle.platform.object.ObjectManager; import io.cattle.platform.server.context.ServerContext; import io.cattle.platform.server.context.ServerContext.BaseProtocol; import io.cattle.platform.service.launcher.GenericServiceLauncher; import io.cattle.platform.ssh.common.SshKeyGen; import io.cattle.platform.token.impl.RSAKeyProvider; import io.cattle.platform.token.impl.RSAPrivateKeyHolder; import io.cattle.platform.util.type.InitializationTask; import io.github.ibuildthecloud.gdapi.condition.Condition; import io.github.ibuildthecloud.gdapi.condition.ConditionType; import java.io.IOException; import java.security.PublicKey; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.inject.Inject; import org.apache.http.client.fluent.Request; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.netflix.config.DynamicBooleanProperty; import com.netflix.config.DynamicPropertyFactory; import com.netflix.config.DynamicStringProperty; public class AuthServiceLauncher extends GenericServiceLauncher implements InitializationTask { @Inject RSAKeyProvider keyProvider; @Inject ObjectManager objectManager; private static final Logger log = LoggerFactory.getLogger(AuthServiceLauncher.class); private static final DynamicStringProperty AUTH_SERVICE_BINARY = ArchaiusUtil.getString("auth.service.executable"); private static final DynamicBooleanProperty LAUNCH_AUTH_SERVICE = ArchaiusUtil.getBoolean("auth.service.execute"); public static final DynamicStringProperty SECURITY_SETTING = ArchaiusUtil.getString("api.security.enabled"); public static final DynamicStringProperty EXTERNAL_AUTH_PROVIDER_SETTING = ArchaiusUtil.getString("api.auth.external.provider.configured"); public static final DynamicStringProperty NO_IDENTITY_LOOKUP_SETTING = ArchaiusUtil.getString("api.auth.external.provider.no.identity.lookup"); @Override protected boolean shouldRun() { return LAUNCH_AUTH_SERVICE.get(); } @Override protected String binaryPath() { return AUTH_SERVICE_BINARY.get(); } @Override protected void setEnvironment(Map<String, String> env) { Credential cred = getCredential(); env.put("CATTLE_ACCESS_KEY", cred.getPublicValue()); env.put("CATTLE_SECRET_KEY", cred.getSecretValue()); env.put("CATTLE_URL", ServerContext.getLocalhostUrl(BaseProtocol.HTTP)); String pubKey = getPublicKey(); if (pubKey == null) { throw new RuntimeException("Couldn't get public key for auth-service."); } env.put("RSA_PUBLIC_KEY_CONTENTS", pubKey); String privateKey = getPrivateKey(); if (privateKey == null) { throw new RuntimeException("Couldn't get private key for auth-service."); } env.put("RSA_PRIVATE_KEY_CONTENTS", privateKey); } @Override protected LockDefinition getLock() { return null; } @Override protected boolean isReady() { return true; } public String getPublicKey() { for (Map.Entry<String, PublicKey> entry : keyProvider.getPublicKeys().entrySet()) { try { return SshKeyGen.writePublicKey(entry.getValue()); } catch (Exception e) { log.error("getPublicKey: Failed to write PEM", e); } } return null; } public String getPrivateKey() { RSAPrivateKeyHolder keyHolder = keyProvider.getPrivateKey(); if(keyHolder == null) { return null; } try { return SshKeyGen.toPEM(keyProvider.getPrivateKey().getKey()); } catch (Exception e) { log.error("getPrivateKey: Failed to write PEM", e); return null; } } @Override protected List<DynamicStringProperty> getReloadSettings() { List<DynamicStringProperty> list = new ArrayList<DynamicStringProperty>(); list.add(SecurityConstants.AUTH_PROVIDER); list.add(SecurityConstants.AUTH_ENABLER_SETTING); list.add(SECURITY_SETTING); list.add(ServiceAuthConstants.ACCESS_MODE); list.add(ServiceAuthConstants.ALLOWED_IDENTITIES); list.add(EXTERNAL_AUTH_PROVIDER_SETTING); list.add(NO_IDENTITY_LOOKUP_SETTING); list.add(ServiceAuthConstants.USER_TYPE); list.add(ServiceAuthConstants.IDENTITY_SEPARATOR); //read Db settings name starting with "api.auth" to add additional provider specific settings List<Setting> settings = objectManager.find(Setting.class, SETTING.NAME, new Condition(ConditionType.LIKE, "api.auth%")); for (Setting setting : settings) { list.add(DynamicPropertyFactory.getInstance().getStringProperty(setting.getName(), null)); } return list; } @Override public void reload() { if (!shouldRun()) { return; } try { StringBuilder authUrl = new StringBuilder(ServiceAuthConstants.AUTH_SERVICE_URL.get()); Request.Post(authUrl+"/reload").execute(); } catch (IOException e) { log.info("Failed to reload auth service: {}", e.getMessage()); } } }