// Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the // License is located at // // http://aws.amazon.com/apache2.0/ // // or in the "license" file accompanying this file. This file 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 ssmparameterresolver provides helper methods to detect, validate and extract parameter store parameter references. package ssmparameterresolver import ( "errors" "strings" "github.com/aws/amazon-ssm-agent/agent/context" "github.com/aws/amazon-ssm-agent/agent/log" "github.com/aws/amazon-ssm-agent/agent/ssm" ) // ISsmParameterService interface represents SSM Parameter service API. type ISsmParameterService interface { getParameters(log log.T, parameterReferences []string) (map[string]SsmParameterInfo, error) } // SsmParameterService structure represents an SSM parameter service and implements ISsmParameterService interface. type SsmParameterService struct { ISsmParameterService sdk ssm.Service } // NewService creates an instance of the SsmParameterService. func NewService(context context.T) (service ISsmParameterService) { return &SsmParameterService{sdk: ssm.NewService(context)} } // This function takes a list of at most maxParametersRetrievedFromSsm(=10) ssm parameter name references like (ssm:name). // It returns a map. func (s *SsmParameterService) getParameters( log log.T, parameterReferences []string) (map[string]SsmParameterInfo, error) { ref2NameMapper := make(map[string]string) for i := 0; i < len(parameterReferences); i++ { nameWithoutPrefix := extractParameterNameFromReference(parameterReferences[i]) ref2NameMapper[nameWithoutPrefix] = parameterReferences[i] parameterReferences[i] = nameWithoutPrefix } parametersOutput, err := s.sdk.GetDecryptedParameters(log, parameterReferences) if err != nil { return nil, err } if len(parametersOutput.InvalidParameters) > 0 { invalidParameters := []string{} for _, p := range parametersOutput.InvalidParameters { invalidParameters = append(invalidParameters, *p) } return nil, errors.New("The following parameter(s) cannot be resolved: " + strings.Join(invalidParameters, ",")) } resolvedParametersMap := map[string]SsmParameterInfo{} for i := 0; i < len(parametersOutput.Parameters); i++ { param := parametersOutput.Parameters[i] resolvedParametersMap[ref2NameMapper[*param.Name]] = SsmParameterInfo{ Name: *param.Name, Type: *param.Type, Value: *param.Value, } } return resolvedParametersMap, nil } // getParametersFromSsmParameterStore takes as an input a list of references // to the SSMParameterService and return a map func getParametersFromSsmParameterStore( s ISsmParameterService, log log.T, parametersToFetch []string) (map[string]SsmParameterInfo, error) { outputMap := make(map[string]SsmParameterInfo) var totalParams = len(parametersToFetch) var startPos = 0 for totalParams > 0 { var paramsBatch []string var count = 0 for i := startPos; i < len(parametersToFetch) && count < maxParametersRetrievedFromSsm; i++ { paramsBatch = append(paramsBatch, parametersToFetch[i]) totalParams-- count++ startPos++ } results, err := s.getParameters(log, paramsBatch) if err != nil { return nil, err } for name, value := range results { outputMap[name] = value } } return outputMap, nil } func extractParameterNameFromReference(parameterReference string) string { return parameterReference[strings.Index(parameterReference, ":")+1:] }