All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.graylog.integrations.aws.AWSAuthFactory Maven / Gradle / Ivy

There is a newer version: 6.1.4
Show newest version
/*
 * Copyright (C) 2020 Graylog, Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the Server Side Public License, version 1,
 * as published by MongoDB, Inc.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * Server Side Public License for more details.
 *
 * You should have received a copy of the Server Side Public License
 * along with this program. If not, see
 * .
 */
package org.graylog.integrations.aws;

import com.google.common.base.Preconditions;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sts.StsClient;
import software.amazon.awssdk.services.sts.auth.StsAssumeRoleCredentialsProvider;
import software.amazon.awssdk.services.sts.model.AssumeRoleRequest;
import software.amazon.awssdk.services.sts.model.GetCallerIdentityRequest;

import javax.annotation.Nullable;
import java.util.Locale;

import static com.google.common.base.Strings.isNullOrEmpty;

public class AWSAuthFactory {
    private static final Logger LOG = LoggerFactory.getLogger(AWSAuthFactory.class);

    /**
     * Resolves the appropriate AWS authorization provider based on the input.
     * If an {@code accessKey} and {@code secretKey} are provided, they will be used explicitly.
     * If not, the default DefaultCredentialsProvider will be used instead. This will resolve the role/policy
     * using Java props, environment variables, EC2 instance roles etc. See the {@link DefaultCredentialsProvider}
     * Javadoc for more information.
     */
    public static AwsCredentialsProvider create(boolean isCloud,
                                                @Nullable String stsRegion,
                                                @Nullable String accessKey,
                                                @Nullable String secretKey,
                                                @Nullable String assumeRoleArn) {
        AwsCredentialsProvider awsCredentials = isCloud ? getCloudAwsCredentialsProvider(accessKey, secretKey) :
                getAwsCredentialsProvider(accessKey, secretKey);

        // Apply the Assume Role ARN Authorization if specified. All AWSCredentialsProviders support this.
        if (!isNullOrEmpty(assumeRoleArn) && !isNullOrEmpty(stsRegion)) {
            LOG.debug("Creating cross account assume role credentials");
            return buildStsCredentialsProvider(awsCredentials, stsRegion, assumeRoleArn, accessKey);
        }

        return awsCredentials;
    }

    private static AwsCredentialsProvider getAwsCredentialsProvider(String accessKey, String secretKey) {
        AwsCredentialsProvider awsCredentials;
        if (!isNullOrEmpty(accessKey) && !isNullOrEmpty(secretKey)) {
            LOG.debug("Using explicitly provided key and secret.");
            awsCredentials = StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKey, secretKey));
        } else {
            LOG.debug("Using default authorization provider chain.");
            awsCredentials = DefaultCredentialsProvider.create();
        }
        return awsCredentials;
    }

    private static AwsCredentialsProvider getCloudAwsCredentialsProvider(String accessKey, String secretKey) {
        Preconditions.checkArgument(StringUtils.isNotBlank(accessKey), "Access key is required.");
        Preconditions.checkArgument(StringUtils.isNotBlank(secretKey), "Secret key is required.");
        return StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKey, secretKey));
    }

    /**
     * Build a new AwsCredentialsProvider instance which will assume the indicated role.
     * Note: In order to assume a role, a role must be provided to the AWS STS client a role that has the "sts:AssumeRole"
     * permission, which provides authorization for a role to be assumed.
     */
    private static AwsCredentialsProvider buildStsCredentialsProvider(AwsCredentialsProvider awsCredentials, String stsRegion,
                                                                      String assumeRoleArn, @Nullable String accessKey) {

        StsClient stsClient = StsClient.builder().region(Region.of(stsRegion)).credentialsProvider(awsCredentials).build();

        // The custom roleSessionName is extra metadata, which will be logged in AWS CloudTrail with each request
        // to help with auditing and debugging.
        final String roleSessionName;
        if (accessKey != null) {
            roleSessionName = String.format(Locale.ROOT, "ACCESS_KEY_%s@ACCOUNT_%s", accessKey,
                    stsClient.getCallerIdentity(GetCallerIdentityRequest.builder().build()).account());
        } else {
            roleSessionName = String.format(Locale.ROOT, "ACCOUNT_%s",
                    stsClient.getCallerIdentity(GetCallerIdentityRequest.builder().build()).account());
        }

        LOG.debug("Cross account role session name: " + roleSessionName);
        return StsAssumeRoleCredentialsProvider.builder().refreshRequest(AssumeRoleRequest.builder()
                        .roleSessionName(roleSessionName)
                        .roleArn(assumeRoleArn)
                        .build())
                .stsClient(stsClient)
                .build();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy