github.com/myhau/pulumi/pkg/v3@v3.70.2-0.20221116134521-f2775972e587/backend/httpstate/crypto.go (about)

     1  // Copyright 2016-2019, Pulumi Corporation.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package httpstate
    16  
    17  import (
    18  	"github.com/pulumi/pulumi/pkg/v3/secrets"
    19  	"github.com/pulumi/pulumi/pkg/v3/secrets/service"
    20  	"github.com/pulumi/pulumi/sdk/v3/go/common/tokens"
    21  	"github.com/pulumi/pulumi/sdk/v3/go/common/util/contract"
    22  	"github.com/pulumi/pulumi/sdk/v3/go/common/workspace"
    23  )
    24  
    25  func NewServiceSecretsManager(s Stack, stackName tokens.Name, configFile string) (secrets.Manager, error) {
    26  	contract.Assertf(stackName != "", "stackName %s", "!= \"\"")
    27  
    28  	project, _, err := workspace.DetectProjectStackPath(stackName.Q())
    29  	if err != nil {
    30  		return nil, err
    31  	}
    32  
    33  	info, err := workspace.LoadProjectStack(project, configFile)
    34  	if err != nil {
    35  		return nil, err
    36  	}
    37  
    38  	client := s.Backend().(Backend).Client()
    39  	id := s.StackIdentifier()
    40  
    41  	// We should only save the ProjectStack at this point IF we have changed the
    42  	// secrets provider. To change the secrets provider to a serviceSecretsManager
    43  	// we would need to ensure that there are no remnants of the old secret manager
    44  	// To remove those remnants, we would set those values to be empty in the project
    45  	// stack, as per changeProjectStackSecretDetails func.
    46  	// If we do not check to see if the secrets provider has changed, then we will actually
    47  	// reload the configuration file to be sorted or an empty {} when creating a stack
    48  	// this is not the desired behaviour.
    49  	if changeProjectStackSecretDetails(info) {
    50  		if err := workspace.SaveProjectStack(stackName.Q(), info); err != nil {
    51  			return nil, err
    52  		}
    53  	}
    54  
    55  	return service.NewServiceSecretsManager(client, id)
    56  }
    57  
    58  // A passphrase secrets provider has an encryption salt, therefore, changing
    59  // from passphrase to serviceSecretsManager requires the encryption salt
    60  // to be removed.
    61  // A cloud secrets manager has an encryption key and a secrets provider,
    62  // therefore, changing from cloud to serviceSecretsManager requires the
    63  // encryption key and secrets provider to be removed.
    64  // Regardless of what the current secrets provider is, all of these values
    65  // need to be empty otherwise `getStackSecretsManager` in crypto.go can
    66  // potentially return the incorrect secret type for the stack.
    67  func changeProjectStackSecretDetails(info *workspace.ProjectStack) bool {
    68  	var requiresSave bool
    69  	if info.SecretsProvider != "" {
    70  		info.SecretsProvider = ""
    71  		requiresSave = true
    72  	}
    73  	if info.EncryptedKey != "" {
    74  		info.EncryptedKey = ""
    75  		requiresSave = true
    76  	}
    77  	if info.EncryptionSalt != "" {
    78  		info.EncryptionSalt = ""
    79  		requiresSave = true
    80  	}
    81  	return requiresSave
    82  }