Repository: codenotary/immudb
File: embedded/remotestorage/s3/s3.go (Go)

Code before:
	s3CredentialsRefreshTicker := time.NewTicker(s.awsCredsRefreshPeriod)
	go func() {
		for {
			select {
			case _ = <-s3CredentialsRefreshTicker.C:
				accessKeyID, secretKey, sessionToken, err := s.requestCredentials()
				if err != nil {
					log.Printf("S3 role credentials lookup failed with an error: %v", err)
					continue
				}
				s.accessKeyID, s.secretKey, s.sessionToken = accessKeyID, secretKey, sessionToken
			}
		}
	}()

	return nil
}

func (s *Storage) requestCredentials() (string, string, string, error) {
	if s.fargateCredentials {
		// Use Fargate credentials
		fargateCredentialsRelativeURI := os.Getenv("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI")
		if fargateCredentialsRelativeURI == "" {
      return "", "", "", errors.New(fmt.Sprintf("environment variable %s is not set or empty", "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"))
    }
		fargateCredentialsURL := fmt.Sprintf("%s%s", "http://169.254.170.2", fargateCredentialsRelativeURI)

		fargateReq, err := http.NewRequest("GET", fargateCredentialsURL, nil)
		if err != nil {
			return "", "", "", errors.New("cannot form fargate credentials request")
		}

		fargateResp, err := http.DefaultClient.Do(fargateReq)
		if err != nil {
			return "", "", "", errors.New("cannot get fargate credentials")
		}
		defer fargateResp.Body.Close()

		creds, err := ioutil.ReadAll(fargateResp.Body)
		if err != nil {
			return "", "", "", errors.New("cannot read fargate credentials")
		}

		var credentials struct {
			AccessKeyID     string `json:"AccessKeyId"`
			SecretAccessKey string `json:"SecretAccessKey"`
			SessionToken    string `json:"Token"`
		}
		if err := json.Unmarshal(creds, &credentials); err != nil {
			return "", "", "", errors.New("cannot parse fargate credentials")
		}

Review comment (refactor):
Can we extract the string `http://169.254.170.2` to a `FargateMetadataEndpoint` const?

I would also just use simple string concatenation in this case rather than `fmt.Sprintf`.

Code after:
	s3CredentialsRefreshTicker := time.NewTicker(s.awsCredsRefreshPeriod)
	go func() {
		for {
			select {
			case _ = <-s3CredentialsRefreshTicker.C:
				accessKeyID, secretKey, sessionToken, err := s.requestCredentials()
				if err != nil {
					log.Printf("S3 role credentials lookup failed with an error: %v", err)
					continue
				}
				s.accessKeyID, s.secretKey, s.sessionToken = accessKeyID, secretKey, sessionToken
			}
		}
	}()

	return nil
}

func (s *Storage) requestCredentials() (string, string, string, error) {
	if s.useFargateCredentials {
		// Use Fargate credentials

		const fargateMetadataEndpoint = "http://169.254.170.2"

		fargateCredentialsRelativeURI := os.Getenv("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI")
		if fargateCredentialsRelativeURI == "" {
			return "", "", "", errors.New("environment variable AWS_CONTAINER_CREDENTIALS_RELATIVE_URI is not set or empty")
		}
		fargateCredentialsURL := fargateMetadataEndpoint + fargateCredentialsRelativeURI

		fargateReq, err := http.NewRequest("GET", fargateCredentialsURL, nil)
		if err != nil {
			return "", "", "", errors.New("cannot form fargate credentials request")
		}

		fargateResp, err := http.DefaultClient.Do(fargateReq)
		if err != nil {
			return "", "", "", errors.New("cannot get fargate credentials")
		}
		defer fargateResp.Body.Close()

		creds, err := io.ReadAll(fargateResp.Body)
		if err != nil {
			return "", "", "", errors.New("cannot read fargate credentials")
		}

		var credentials struct {
			AccessKeyID     string `json:"AccessKeyId"`
			SecretAccessKey string `json:"SecretAccessKey"`
			SessionToken    string `json:"Token"`
		}