AWS – Secrets Manager

 

This service has been a blessing for me in terms of hiding credentials from being exposed to hackers. This is what Secrets Manager does from the official site.

“AWS Secrets Manager helps you protect secrets needed to access your applications, services, and IT resources. The service enables you to easily rotate, manage, and retrieve database credentials, API keys, and other secrets throughout their lifecycle. Users and applications retrieve secrets with a call to Secrets Manager APIs, eliminating the need to hardcode sensitive information in plain text. Secrets Manager offers secret rotation with built-in integration for Amazon RDS, Amazon Redshift, and Amazon DocumentDB. Also, the service is extensible to other types of secrets, including API keys and OAuth tokens. In addition, Secrets Manager enables you to control access to secrets using fine-grained permissions and audit secret rotation centrally for resources in the AWS Cloud, third-party services, and on-premises.”

How to implement:

Include this dependency in your pom file.

<dependency>
			<groupId>com.amazonaws</groupId>
			<artifactId>aws-java-sdk-secretsmanager</artifactId>
		</dependency>

 

Configure an AWSSecretsManager bean or object.

@Configuration
public class DevConfig {
    private Logger                 log = LoggerFactory.getLogger(this.getClass());
    
    @Autowired
    private AWSSecretsManagerUtils awsSecretsManagerUtils;
    
	@Bean
	public AWSCredentialsProvider amazonAWSCredentialsProvider() {
		
		return DefaultAWSCredentialsProviderChain.getInstance();
	}
	
	@Bean
	public AWSSecretsManager awsSecretsManager() {
		AWSSecretsManager awsSecretsManager = AWSSecretsManagerClientBuilder
				.standard()
				.withCredentials(amazonAWSCredentialsProvider())
				.withRegion(Regions.US_WEST_2)
				.build();
		
		return awsSecretsManager;
	}
    
    @Bean
    public HikariDataSource dataSource() {
        //log.debug("DB SECRET: {}", dbSecret.toJson());
    	
    	DbSecret dbSecret = awsSecretsManagerUtils.getDbSecret();

        log.info("Configuring dev datasource...");
        Integer port = 3306;
        String host = dbSecret.getHost();
        String username = dbSecret.getUsername();
        String password = dbSecret.getPassword();
        String dbName = "springboot-course-tshirt";
        String url = "jdbc:mysql://" + host + ":" + port + "/" + dbName + "?useUnicode=true&characterEncoding=utf8&useSSL=false";
        
        HikariConfig config = new HikariConfig();
		config.setJdbcUrl(url);
		config.setUsername(username);
		config.setPassword(password);

		HikariDataSource hds = new HikariDataSource(config);
		hds.setMaximumPoolSize(30);
		hds.setMinimumIdle(20);
		hds.setMaxLifetime(1800000);
		hds.setConnectionTimeout(30000);
		hds.setIdleTimeout(600000);
		
		return hds;
    }
   
}
	

Use the service by retrieving a mysql server database.

@Component
public class AWSSecretsManagerUtils {
	private Logger log = LoggerFactory.getLogger(AWSSecretsManagerUtils.class);

	@Value("${datasource.secret.name}")
	private String dataSourceSecretName;

	@Autowired
	private AWSSecretsManager awsSecretsManager;

	public DbSecret getDbSecret() {
		return DbSecret.fromJson(getCredentials(dataSourceSecretName));
	}
	
	private String getCredentials(String secretId) {
		GetSecretValueRequest getSecretValueRequest = new GetSecretValueRequest();
		getSecretValueRequest.setSecretId(secretId);

		GetSecretValueResult getSecretValueResponse = null;
		try {
			getSecretValueResponse = awsSecretsManager.getSecretValue(getSecretValueRequest);
		} catch (Exception e) {
			log.error("Exception, msg: ", e.getMessage());
		}

		if (getSecretValueResponse == null) {
			return null;
		}

		ByteBuffer binarySecretData;
		String secret;
		// Decrypted secret using the associated KMS CMK
		// Depending on whether the secret was a string or binary, one of these fields
		// will be populated
		if (getSecretValueResponse.getSecretString() != null) {
			log.info("secret string");
			secret = getSecretValueResponse.getSecretString();
		} else {
			log.info("secret binary secret data");
			binarySecretData = getSecretValueResponse.getSecretBinary();
			secret = binarySecretData.toString();
		}
		
		return secret;
	}
}
public class DbSecret {
	private String username;

	private String password;
	
	private String engine;
	
	private String host;
	
	private String dbInstanceIdentifier;
	

	public DbSecret() {
		this(null,null,null,null,null);
	}

	public DbSecret(String username, String password, String engine, String host,
			String dbInstanceIdentifier) {
		super();
		this.username = username;
		this.password = password;
		this.engine = engine;
		this.host = host;
		this.dbInstanceIdentifier = dbInstanceIdentifier;
	}

	// setters and getters
	
	public String toJson() {
		try {
			return ObjectUtils.getObjectMapper().writeValueAsString(this);
		} catch (JsonProcessingException e) {
			System.out.println("JsonProcessingException, msg: " + e.getLocalizedMessage());
			return "{}";
		}
	}
	
	public static DbSecret fromJson(String json) {
		
		try {
			return ObjectUtils.getObjectMapper().readValue(json, DbSecret.class);
		} catch (IOException e) {
			System.out.println("From Json Exception: "+e.getLocalizedMessage());
			return null;
		}
	}
}

SecretsManager with AWS CLI

Get list of secrets

aws secretsmanager list-secrets --profile {profile-name}

Get secret values

aws secretsmanager get-secret-value --secret-id {secretName or ARN} --profile {profile-name}  

 




Subscribe To Our Newsletter
You will receive our latest post and tutorial.
Thank you for subscribing!

required
required


Leave a Reply

Your email address will not be published.