Current section

Files

Jump to
nextroll_erlcloud src erlcloud_config.erl
Raw

src/erlcloud_config.erl

-module(erlcloud_config).
-include("erlcloud_aws.hrl").
-include("erlcloud.hrl").
%% API
-export([new/2, new/3, new/4, new/5,
configure/3, configure/4, configure/5, configure/6]).
-export([
describe_compliance_by_config_rule/2,
describe_compliance_by_resource/2,
describe_config_rule_evaluation_status/2,
describe_config_rules/2,
describe_configuration_recorders/2,
describe_configuration_recorder_status/2,
describe_delivery_channels/2,
describe_delivery_channel_status/2,
get_compliance_details_by_config_rule/3,
get_compliance_details_by_resource/4,
get_compliance_summary_by_config_rule/1,
get_compliance_summary_by_resource_type/2,
get_discovered_resource_counts/2,
get_resource_config_history/4,
list_discovered_resources/3
]).
-define(LIMIT_MAX, 100).
-define(CONFIG_RULE_NAMES, <<"ConfigRuleNames">>).
-define(CONFIG_RULE_NAME, <<"ConfigRuleName">>).
-define(COMPLIANCE_TYPES, <<"ComplianceTypes">>).
-define(LIMIT, <<"Limit">>).
-define(RESOURCE_NAME, <<"ResourceName">>).
-define(RESOURCE_ID, <<"ResourceId">>).
-define(RESOURCE_IDS, <<"ResourceIds">>).
-define(RESOURCE_TYPE, <<"ResourceType">>).
-define(RESOURCE_TYPES, <<"ResourceTypes">>).
-define(CONFIGURATION_RECORDER_NAMES, <<"ConfigurationRecorderNames">>).
-define(DELIVERY_CHANNEL_NAMES, <<"DeliveryChannelNames">>).
-define(CHRONOLOGICAL_ORDER, <<"chronologicalOrder">>).
-define(EARLIER_TIME, <<"earlierTime">>).
-define(LATER_TIME, <<"laterTime">>).
-define(INCLUDE_DELETED_RESOURCES, <<"includeDeletedResources">>).
%%------------------------------------------------------------------------------
%% Library initialization.
%%------------------------------------------------------------------------------
-spec new(string(), string()) -> aws_config().
new(AccessKeyID, SecretAccessKey) ->
#aws_config{access_key_id = AccessKeyID,
secret_access_key = SecretAccessKey,
retry = fun erlcloud_retry:default_retry/1}.
-spec new(string(), string(), string()) -> aws_config().
new(AccessKeyID, SecretAccessKey, Host) ->
#aws_config{access_key_id = AccessKeyID,
secret_access_key = SecretAccessKey,
config_host = Host,
retry = fun erlcloud_retry:default_retry/1}.
-spec new(string(), string(), string(), non_neg_integer()) -> aws_config().
new(AccessKeyID, SecretAccessKey, Host, Port) ->
#aws_config{access_key_id = AccessKeyID,
secret_access_key = SecretAccessKey,
config_host = Host,
config_port = Port,
retry = fun erlcloud_retry:default_retry/1}.
-spec new(string(), string(), string(), non_neg_integer(), string()) ->
aws_config().
new(AccessKeyID, SecretAccessKey, Host, Port, Scheme) ->
#aws_config{access_key_id = AccessKeyID,
secret_access_key = SecretAccessKey,
config_host = Host,
config_port = Port,
config_scheme = Scheme,
retry = fun erlcloud_retry:default_retry/1}.
%%------------------------------------------------------------------------------
%% AWS Config API Functions
%%------------------------------------------------------------------------------
-spec configure(string(), string(), function()) -> ok.
configure(AccessKeyID, SecretAccessKey, New)
when is_list(AccessKeyID), is_list(SecretAccessKey), is_function(New, 2) ->
put(aws_config, New(AccessKeyID, SecretAccessKey)),
ok.
-spec configure(string(), string(), string(), function()) -> ok.
configure(AccessKeyID, SecretAccessKey, Host, New)
when is_list(AccessKeyID), is_list(SecretAccessKey), is_list(Host), is_function(New, 3) ->
put(aws_config, New(AccessKeyID, SecretAccessKey, Host)),
ok.
-spec configure(string(), string(), string(), non_neg_integer(), function()) -> ok.
configure(AccessKeyID, SecretAccessKey, Host, Port, New)
when is_list(AccessKeyID), is_list(SecretAccessKey),
is_list(Host), is_function(New, 4) ->
put(aws_config, New(AccessKeyID, SecretAccessKey, Host, Port)),
ok.
-spec configure(string(), string(), string(), non_neg_integer(), string(), function()) -> ok.
configure(AccessKeyID, SecretAccessKey, Host, Port, Scheme, New)
when is_list(AccessKeyID), is_list(SecretAccessKey), is_list(Host),
is_list(Scheme), is_function(New, 5) ->
put(aws_config, New(AccessKeyID, SecretAccessKey, Host, Port, Scheme)),
ok.
%%------------------------------------------------------------------------------
%% @doc
%% DescribeComplianceByConfigRule
%%
%% https://docs.aws.amazon.com/config/latest/APIReference/API_DescribeComplianceByConfigRule.html
%%------------------------------------------------------------------------------
-spec describe_compliance_by_config_rule(Opts :: map(),
Config :: aws_config()) ->
result_paged(map()).
describe_compliance_by_config_rule(Opts, Config) when is_map(Opts) orelse Opts =:= #{} ->
Request = #{?COMPLIANCE_TYPES => maps:get(?COMPLIANCE_TYPES, Opts, []),
?CONFIG_RULE_NAMES => maps:get(?CONFIG_RULE_NAMES, Opts, []),
?NEXT_TOKEN_LABEL => maps:get(?NEXT_TOKEN_LABEL, Opts, null)
},
request(Config, "DescribeComplianceByConfigRule", Request).
%%------------------------------------------------------------------------------
%% @doc
%% DescribeComplianceByResource
%%
%% https://docs.aws.amazon.com/config/latest/APIReference/API_DescribeComplianceByResource.html
%%------------------------------------------------------------------------------
-spec describe_compliance_by_resource(Opts :: map(),
Config :: aws_config()) ->
result_paged(map()).
describe_compliance_by_resource(Opts, Config) when is_map(Opts) orelse Opts =:= #{} ->
Request = #{?COMPLIANCE_TYPES => maps:get(?COMPLIANCE_TYPES, Opts, []),
?LIMIT => maps:get(?LIMIT, Opts, ?LIMIT_MAX),
?NEXT_TOKEN_LABEL => maps:get(?NEXT_TOKEN_LABEL, Opts, null),
?RESOURCE_ID => maps:get(?RESOURCE_ID, Opts, null),
?RESOURCE_TYPE => maps:get(?RESOURCE_TYPE, Opts, null)
},
request(Config, "DescribeComplianceByResource", Request).
%%------------------------------------------------------------------------------
%% @doc
%% DescribeConfigRuleEvaluationStatus
%%
%% https://docs.aws.amazon.com/config/latest/APIReference/API_DescribeConfigRuleEvaluationStatus.html
%%------------------------------------------------------------------------------
-spec describe_config_rule_evaluation_status(Opts :: map(),
Config :: aws_config()) ->
result_paged(map()).
describe_config_rule_evaluation_status(Opts, Config) when is_map(Opts) orelse Opts =:= #{} ->
Request = #{?CONFIG_RULE_NAMES => maps:get(?CONFIG_RULE_NAMES, Opts, []),
?LIMIT => maps:get(?LIMIT, Opts, ?LIMIT_MAX),
?NEXT_TOKEN_LABEL => maps:get(?NEXT_TOKEN_LABEL, Opts, null)
},
request(Config, "DescribeConfigRuleEvaluationStatus", Request).
%%------------------------------------------------------------------------------
%% @doc
%% DescribeConfigRules
%%
%% https://docs.aws.amazon.com/config/latest/APIReference/API_DescribeConfigRules.html
%%------------------------------------------------------------------------------
-spec describe_config_rules(Opts :: map(),
Config :: aws_config()) ->
result_paged(map()).
describe_config_rules(Opts, Config)
when is_map(Opts) orelse Opts =:= #{} ->
Request = #{?CONFIG_RULE_NAMES => maps:get(?CONFIG_RULE_NAMES, Opts, []),
?NEXT_TOKEN_LABEL => maps:get(?NEXT_TOKEN_LABEL, Opts, null)
},
request(Config, "DescribeConfigRules", Request).
%%------------------------------------------------------------------------------
%% @doc
%% DescribeConfigurationRecorders
%%
%% https://docs.aws.amazon.com/config/latest/APIReference/API_DescribeConfigurationRecorders.html
%%------------------------------------------------------------------------------
-spec describe_configuration_recorders(Opts :: map(),
Config :: aws_config()) ->
result_paged(map()).
describe_configuration_recorders(Opts, Config) when is_map(Opts) orelse Opts =:= #{} ->
Request = #{?CONFIGURATION_RECORDER_NAMES => maps:get(?CONFIGURATION_RECORDER_NAMES, Opts, [])},
request(Config, "DescribeConfigurationRecorders", Request).
%%------------------------------------------------------------------------------
%% @doc
%% DescribeConfigurationRecorderStatus
%%
%% https://docs.aws.amazon.com/config/latest/APIReference/API_DescribeConfigurationRecorderStatus.html
%%------------------------------------------------------------------------------
-spec describe_configuration_recorder_status(Opts :: map(),
Config :: aws_config()) ->
result_paged(map()).
describe_configuration_recorder_status(Opts, Config) when is_map(Opts) orelse Opts =:= #{} ->
Request = #{?CONFIGURATION_RECORDER_NAMES => maps:get(?CONFIGURATION_RECORDER_NAMES, Opts, [])},
request(Config, "DescribeConfigurationRecorderStatus", Request).
%%------------------------------------------------------------------------------
%% @doc
%% DescribeDeliveryChannels
%%
%% https://docs.aws.amazon.com/config/latest/APIReference/API_DescribeDeliveryChannels.html
%%------------------------------------------------------------------------------
-spec describe_delivery_channels(Opts :: map(),
Config :: aws_config()) ->
result_paged(map()).
describe_delivery_channels(Opts, Config) when is_map(Opts) orelse Opts =:= #{} ->
Request = #{?DELIVERY_CHANNEL_NAMES => maps:get(?DELIVERY_CHANNEL_NAMES, Opts, [])},
request(Config, "DescribeDeliveryChannels", Request).
%%------------------------------------------------------------------------------
%% @doc
%% DescribeDeliveryChannelStatus
%%
%% https://docs.aws.amazon.com/config/latest/APIReference/API_DescribeDeliveryChannelStatus.html
%%------------------------------------------------------------------------------
-spec describe_delivery_channel_status(Opts :: map(),
Config :: aws_config()) ->
result_paged(map()).
describe_delivery_channel_status(Opts, Config) when is_map(Opts) orelse Opts =:= #{} ->
Request = #{?DELIVERY_CHANNEL_NAMES => maps:get(?DELIVERY_CHANNEL_NAMES, Opts, [])},
request(Config, "DescribeDeliveryChannelStatus", Request).
%%------------------------------------------------------------------------------
%% @doc
%% GetComplianceDetailsByConfigRule
%%
%% https://docs.aws.amazon.com/config/latest/APIReference/API_GetComplianceDetailsByConfigRule.html
%%------------------------------------------------------------------------------
-spec get_compliance_details_by_config_rule(ConfigRuleName :: binary(),
Opts :: map(),
Config :: aws_config()) ->
result_paged(map()).
get_compliance_details_by_config_rule(ConfigRuleName, Opts, Config) when is_map(Opts) orelse Opts =:= #{} ->
Request = #{?COMPLIANCE_TYPES => maps:get(?COMPLIANCE_TYPES, Opts, []),
?CONFIG_RULE_NAME => ConfigRuleName,
?LIMIT => maps:get(?LIMIT, Opts, ?LIMIT_MAX),
?NEXT_TOKEN_LABEL => maps:get(?NEXT_TOKEN_LABEL, Opts, null)},
request(Config, "GetComplianceDetailsByConfigRule", Request).
%%------------------------------------------------------------------------------
%% @doc
%% GetComplianceDetailsByResource
%%
%% https://docs.aws.amazon.com/config/latest/APIReference/API_GetComplianceDetailsByResource.html
%%------------------------------------------------------------------------------
-spec get_compliance_details_by_resource(ResourceId :: binary(),
ResourceType :: binary(),
Opts :: map(),
Config :: aws_config()) ->
result_paged(map()).
get_compliance_details_by_resource(ResourceId, ResourceType, Opts, Config) when is_map(Opts) orelse Opts =:= #{} ->
Request = #{?COMPLIANCE_TYPES => maps:get(?COMPLIANCE_TYPES, Opts, []),
?NEXT_TOKEN_LABEL => maps:get(?NEXT_TOKEN_LABEL, Opts, null),
?RESOURCE_ID => ResourceId,
?RESOURCE_TYPE => ResourceType},
request(Config, "GetComplianceDetailsByResource", Request).
%%------------------------------------------------------------------------------
%% @doc
%% GetComplianceSummaryByConfigRule
%%
%% https://docs.aws.amazon.com/config/latest/APIReference/API_GetComplianceSummaryByConfigRule.html
%%------------------------------------------------------------------------------
-spec get_compliance_summary_by_config_rule(Config :: aws_config()) ->
result_paged(map()).
get_compliance_summary_by_config_rule(Config) ->
request(Config, "GetComplianceSummaryByConfigRule", #{}).
%%------------------------------------------------------------------------------
%% @doc
%% GetComplianceSummaryByResourceType
%%
%% https://docs.aws.amazon.com/config/latest/APIReference/API_GetComplianceSummaryByResourceType.html
%%------------------------------------------------------------------------------
-spec get_compliance_summary_by_resource_type(Opts :: map(),
Config :: aws_config()) ->
result_paged(map()).
get_compliance_summary_by_resource_type(Opts, Config) when is_map(Opts) orelse Opts =:= #{} ->
Request = #{?RESOURCE_TYPES => maps:get(?RESOURCE_TYPES, Opts, [])},
request(Config, "GetComplianceSummaryByResourceType", Request).
%%------------------------------------------------------------------------------
%% @doc
%% GetDiscoveredResourceCounts
%%
%% https://docs.aws.amazon.com/config/latest/APIReference/API_GetDiscoveredResourceCounts.html
%%------------------------------------------------------------------------------
-spec get_discovered_resource_counts(Opts :: map(),
Config :: aws_config()) ->
result_paged(map()).
get_discovered_resource_counts(Opts, Config) when is_map(Opts) orelse Opts =:= #{} ->
Request = #{?LIMIT => maps:get(?LIMIT, Opts, ?LIMIT_MAX),
?NEXT_TOKEN_LABEL => maps:get(?NEXT_TOKEN_LABEL, Opts, null),
?RESOURCE_TYPES => maps:get(?RESOURCE_TYPES, Opts, null)},
request(Config, "GetDiscoveredResourceCounts", Request).
%%------------------------------------------------------------------------------
%% @doc
%% GetResourceConfigHistory
%%
%% https://docs.aws.amazon.com/config/latest/APIReference/API_GetResourceConfigHistory.html
%%------------------------------------------------------------------------------
-spec get_resource_config_history(ResourceId :: binary(),
ResourceType :: binary(),
Opts :: map(),
Config :: aws_config()) ->
result_paged(map()).
get_resource_config_history(ResourceId, ResourceType, Opts, Config) when is_map(Opts) orelse Opts =:= #{} ->
Request = #{?CHRONOLOGICAL_ORDER => maps:get(?CHRONOLOGICAL_ORDER, Opts, null),
?EARLIER_TIME => maps:get(?EARLIER_TIME, Opts, null),
?LATER_TIME => maps:get(?LATER_TIME, Opts, null),
?LIMIT => maps:get(?LIMIT, Opts, ?LIMIT_MAX),
?NEXT_TOKEN_LABEL => maps:get(?NEXT_TOKEN_LABEL, Opts, null),
?RESOURCE_ID => ResourceId,
?RESOURCE_TYPE => ResourceType},
request(Config, "GetResourceConfigHistory", Request).
%%------------------------------------------------------------------------------
%% @doc
%% ListDiscoveredResources
%%
%% https://docs.aws.amazon.com/config/latest/APIReference/API_ListDiscoveredResources.html
%%------------------------------------------------------------------------------
-spec list_discovered_resources(ResourceType :: binary(),
Opts :: map(),
Config :: aws_config()) ->
result_paged(map()).
list_discovered_resources(ResourceType, Opts, Config) when is_map(Opts) orelse Opts =:= #{} ->
Request = #{?INCLUDE_DELETED_RESOURCES => maps:get(?INCLUDE_DELETED_RESOURCES, Opts, true),
?LIMIT => maps:get(?LIMIT, Opts, ?LIMIT_MAX),
?NEXT_TOKEN_LABEL => maps:get(?NEXT_TOKEN_LABEL, Opts, null),
?RESOURCE_IDS => maps:get(?RESOURCE_IDS, Opts, []),
?RESOURCE_NAME => maps:get(?RESOURCE_NAME, Opts, null),
?RESOURCE_TYPE => ResourceType},
request(Config, "ListDiscoveredResources", Request).
%%%------------------------------------------------------------------------------
%%% @doc
%%% Internal Functions
%%%------------------------------------------------------------------------------
request(Config0, OperationName, Request) ->
case erlcloud_aws:update_config(Config0) of
{ok, Config} ->
Body = jsx:encode(Request),
Operation = "StarlingDoveService." ++ OperationName,
Headers = get_headers(Config, Operation, Body),
AwsRequest = #aws_request{service = config,
uri = get_url(Config),
method = post,
request_headers = Headers,
request_body = Body},
request(Config, AwsRequest);
{error, Reason} ->
{error, Reason}
end.
request(Config, Request) ->
Result = erlcloud_retry:request(Config, Request, fun handle_result/1),
case erlcloud_aws:request_to_return(Result) of
{ok, {_, <<>>}} -> {ok, #{}};
{ok, {_, RespBody}} -> {ok, jsx:decode(RespBody)};
{error, _} = Error -> Error
end.
handle_result(#aws_request{response_type = ok} = Request) ->
Request;
handle_result(#aws_request{response_type = error,
error_type = aws,
response_status = Status} = Request)
when Status >= 500 ->
Request#aws_request{should_retry = true};
handle_result(#aws_request{response_type = error,
error_type = aws} = Request) ->
Request#aws_request{should_retry = false}.
get_headers(#aws_config{config_host = Host} = Config, Operation, Body) ->
Headers = [{"host", Host},
{"x-amz-target", Operation},
{"content-type", "application/x-amz-json-1.1"}],
Region = erlcloud_aws:aws_region_from_host(Host),
erlcloud_aws:sign_v4_headers(Config, Headers, Body, Region, "config").
get_url(#aws_config{config_scheme = Scheme,
config_host = Host,
config_port = Port}) ->
Scheme ++ Host ++ ":" ++ integer_to_list(Port).