aws.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. package env
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "strings"
  7. "time"
  8. "github.com/aws/aws-sdk-go-v2/aws"
  9. awsConfig "github.com/aws/aws-sdk-go-v2/config"
  10. "github.com/aws/aws-sdk-go-v2/service/secretsmanager"
  11. "github.com/aws/aws-sdk-go-v2/service/ssm"
  12. )
  13. const (
  14. // defaultAWSRegion represents default AWS region for all configuration
  15. defaultAWSRegion = "us-west-1"
  16. )
  17. var (
  18. IMGPROXY_ENV_AWS_SECRET_ID = Describe("IMGPROXY_ENV_AWS_SECRET_ID", "string")
  19. IMGPROXY_ENV_AWS_SECRET_VERSION_ID = Describe("IMGPROXY_ENV_AWS_SECRET_VERSION_ID", "string")
  20. IMGPROXY_ENV_AWS_SECRET_VERSION_STAGE = Describe("IMGPROXY_ENV_AWS_SECRET_VERSION_STAGE", "string")
  21. IMGPROXY_ENV_AWS_SECRET_REGION = Describe("IMGPROXY_ENV_AWS_SECRET_REGION", "AWS region ("+defaultAWSRegion+")")
  22. IMGPROXY_ENV_AWS_SSM_PARAMETERS_PATH = Describe("IMGPROXY_ENV_AWS_SSM_PARAMETERS_PATH", "string")
  23. IMGPROXY_ENV_AWS_SSM_PARAMETERS_REGION = Describe("IMGPROXY_ENV_AWS_SSM_PARAMETERS_REGION", "AWS region ("+defaultAWSRegion+")")
  24. )
  25. func loadAWSSecret(ctx context.Context) error {
  26. var secretID, secretVersionID, secretVersionStage, secretRegion string
  27. String(&secretID, IMGPROXY_ENV_AWS_SECRET_ID)
  28. String(&secretVersionID, IMGPROXY_ENV_AWS_SECRET_VERSION_ID)
  29. String(&secretVersionStage, IMGPROXY_ENV_AWS_SECRET_VERSION_STAGE)
  30. String(&secretRegion, IMGPROXY_ENV_AWS_SECRET_REGION)
  31. // No secret ID, no aws
  32. if len(secretID) == 0 {
  33. return nil
  34. }
  35. // Let's form AWS default config
  36. conf, err := awsConfig.LoadDefaultConfig(ctx)
  37. if err != nil {
  38. return fmt.Errorf("can't load AWS Secrets Manager config: %s", err)
  39. }
  40. if len(secretRegion) > 0 {
  41. conf.Region = secretRegion
  42. }
  43. if len(conf.Region) == 0 {
  44. conf.Region = defaultAWSRegion
  45. }
  46. // Let's create secrets manager client
  47. client := secretsmanager.NewFromConfig(conf)
  48. input := secretsmanager.GetSecretValueInput{SecretId: aws.String(secretID)}
  49. if len(secretVersionID) > 0 {
  50. input.VersionId = aws.String(secretVersionID)
  51. } else if len(secretVersionStage) > 0 {
  52. input.VersionStage = aws.String(secretVersionStage)
  53. }
  54. ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
  55. defer cancel()
  56. output, err := client.GetSecretValue(ctx, &input)
  57. if err != nil {
  58. return fmt.Errorf("can't retrieve config from AWS Secrets Manager: %s", err)
  59. }
  60. // No secret string, failed to initialize secrets manager, return
  61. if output.SecretString == nil {
  62. return nil
  63. }
  64. return unmarshalEnv(*output.SecretString, "AWS Secrets Manager")
  65. }
  66. // loadAWSSystemManagerParams loads environment variables from AWS System Manager
  67. func loadAWSSystemManagerParams(ctx context.Context) error {
  68. var paramsPath, paramsRegion string
  69. String(&paramsPath, IMGPROXY_ENV_AWS_SSM_PARAMETERS_PATH)
  70. String(&paramsRegion, IMGPROXY_ENV_AWS_SSM_PARAMETERS_REGION)
  71. // Path is not set: can't use SSM
  72. if len(paramsPath) == 0 {
  73. return nil
  74. }
  75. conf, err := awsConfig.LoadDefaultConfig(ctx)
  76. if err != nil {
  77. return fmt.Errorf("can't load AWS SSM config: %s", err)
  78. }
  79. conf.Region = defaultAWSRegion
  80. if len(paramsRegion) != 0 {
  81. conf.Region = paramsRegion
  82. }
  83. // Let's create SSM client
  84. client := ssm.NewFromConfig(conf)
  85. ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
  86. defer cancel()
  87. var nextToken *string
  88. for {
  89. input := ssm.GetParametersByPathInput{
  90. Path: aws.String(paramsPath),
  91. WithDecryption: aws.Bool(true),
  92. NextToken: nextToken,
  93. }
  94. output, err := client.GetParametersByPath(ctx, &input)
  95. if err != nil {
  96. return fmt.Errorf("can't retrieve parameters from AWS SSM: %s", err)
  97. }
  98. for _, p := range output.Parameters {
  99. if p.Name == nil || p.Value == nil {
  100. continue
  101. }
  102. if p.DataType == nil || *p.DataType != "text" {
  103. continue
  104. }
  105. name := *p.Name
  106. env := strings.ReplaceAll(
  107. strings.TrimPrefix(strings.TrimPrefix(name, paramsPath), "/"),
  108. "/", "_",
  109. )
  110. if err = os.Setenv(env, *p.Value); err != nil {
  111. return fmt.Errorf("can't set %s env variable from AWS SSM: %s", env, err)
  112. }
  113. }
  114. if nextToken = output.NextToken; nextToken == nil {
  115. break
  116. }
  117. }
  118. return nil
  119. }