/* * Copyright 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. */ using Amazon.Runtime; using Amazon.Runtime.Internal; using Amazon.Runtime.Internal.Transform; using Amazon.Runtime.Internal.Util; using Amazon.Runtime.SharedInterfaces; using Amazon.Runtime.SharedInterfaces.Internal; using Amazon.S3.Internal; using Amazon.S3.Model; using Amazon.Util; using System; using System.Collections.Generic; using System.Globalization; namespace Amazon.S3.Encryption { /// /// This class extends the AmazonS3Client and provides client side encryption when reading or writing S3 objects. /// [Obsolete("This feature is in maintenance mode, no new updates will be released. " + "Please transition to https://www.nuget.org/packages/Amazon.Extensions.S3.Encryption " + "and see https://docs.aws.amazon.com/general/latest/gr/aws_sdk_cryptography.html for more information.")] public partial class AmazonS3EncryptionClient : AmazonS3Client, IAmazonS3Encryption { private static readonly string S3KMSEncryptionFeature = "the KMS encryption features of " + typeof(AmazonS3EncryptionClient).Name; private ICoreAmazonKMS kmsClient; private readonly object kmsClientLock = new object(); internal EncryptionMaterials EncryptionMaterials { get; private set; } internal ICoreAmazonKMS KMSClient { get { if (kmsClient == null) { lock (kmsClientLock) { if (kmsClient == null) kmsClient = new CoreAmazonKMS(this, S3KMSEncryptionFeature); } } return kmsClient; } } private AmazonS3Client s3ClientForInstructionFile; internal AmazonS3Client S3ClientForInstructionFile { get { if (s3ClientForInstructionFile == null) { s3ClientForInstructionFile = new AmazonS3Client(Credentials, S3CryptoConfig); } return s3ClientForInstructionFile; } } internal AmazonS3CryptoConfiguration S3CryptoConfig { get; private set; } internal Dictionary CurrentMultiPartUploadKeys = new Dictionary(); internal const string S3CryptoStream = "S3-Crypto-Stream"; #region Constructors /// /// Constructs AmazonS3EncryptionClient with the Encryption materials and credentials loaded from the application's /// default configuration, and if unsuccessful from the Instance Profile service on an EC2 instance. /// /// Example App.config with credentials set. /// /// <?xml version="1.0" encoding="utf-8" ?> /// <configuration> /// <appSettings> /// <add key="AWSProfileName" value="AWS Default"/> /// </appSettings> /// </configuration> /// /// /// /// /// The encryption materials to be used to encrypt and decrypt envelope key. /// public AmazonS3EncryptionClient(EncryptionMaterials materials) : base() { this.EncryptionMaterials = materials; S3CryptoConfig = new AmazonS3CryptoConfiguration(); } /// /// Constructs AmazonS3EncryptionClient with the Encryption materials and credentials loaded from the application's /// default configuration, and if unsuccessful from the Instance Profile service on an EC2 instance. /// /// Example App.config with credentials set. /// /// <?xml version="1.0" encoding="utf-8" ?> /// <configuration> /// <appSettings> /// <add key="AWSProfileName" value="AWS Default"/> /// </appSettings> /// </configuration> /// /// /// /// /// The region to connect. /// /// /// The encryption materials to be used to encrypt and decrypt envelope key. /// public AmazonS3EncryptionClient(RegionEndpoint region, EncryptionMaterials materials) : base(region) { this.EncryptionMaterials = materials; S3CryptoConfig = new AmazonS3CryptoConfiguration(); } /// /// Constructs AmazonS3EncryptionClient with the Encryption materials, /// AmazonS3 CryptoConfiguration object and credentials loaded from the application's /// default configuration, and if unsuccessful from the Instance Profile service on an EC2 instance. /// /// Example App.config with credentials set. /// /// <?xml version="1.0" encoding="utf-8" ?> /// <configuration> /// <appSettings> /// <add key="AWSProfileName" value="AWS Default"/> /// </appSettings> /// </configuration> /// /// /// /// /// The AmazonS3EncryptionClient CryptoConfiguration Object /// /// /// The encryption materials to be used to encrypt and decrypt envelope key. /// public AmazonS3EncryptionClient(AmazonS3CryptoConfiguration config, EncryptionMaterials materials) : base(config) { this.EncryptionMaterials = materials; S3CryptoConfig = config; } /// /// Constructs AmazonS3EncryptionClient with AWS Credentials and Encryption materials. /// /// /// The encryption materials to be used to encrypt and decrypt envelope key. /// /// AWS Credentials public AmazonS3EncryptionClient(AWSCredentials credentials, EncryptionMaterials materials) : base(credentials) { this.EncryptionMaterials = materials; S3CryptoConfig = new AmazonS3CryptoConfiguration(); } /// /// Constructs AmazonS3EncryptionClient with AWS Credentials, Region and Encryption materials /// /// AWS Credentials /// The region to connect. /// /// The encryption materials to be used to encrypt and decrypt envelope key. /// public AmazonS3EncryptionClient(AWSCredentials credentials, RegionEndpoint region, EncryptionMaterials materials) : base(credentials, region) { this.EncryptionMaterials = materials; S3CryptoConfig = new AmazonS3CryptoConfiguration(); } /// /// Constructs AmazonS3EncryptionClient with AWS Credentials, AmazonS3CryptoConfiguration Configuration object /// and Encryption materials /// /// AWS Credentials /// The AmazonS3EncryptionClient CryptoConfiguration Object /// /// The encryption materials to be used to encrypt and decrypt envelope key. /// public AmazonS3EncryptionClient(AWSCredentials credentials, AmazonS3CryptoConfiguration config, EncryptionMaterials materials) : base(credentials, config) { this.EncryptionMaterials = materials; S3CryptoConfig = config; } /// /// Constructs AmazonS3EncryptionClient with AWS Access Key ID, /// AWS Secret Key and Encryption materials /// /// AWS Access Key ID /// AWS Secret Access Key /// The encryption materials to be used to encrypt and decrypt envelope key. public AmazonS3EncryptionClient(string awsAccessKeyId, string awsSecretAccessKey, EncryptionMaterials materials) : base(awsAccessKeyId, awsSecretAccessKey) { this.EncryptionMaterials = materials; S3CryptoConfig = new AmazonS3CryptoConfiguration(); } /// /// Constructs AmazonS3EncryptionClient with AWS Access Key ID, /// AWS Secret Key, Region and Encryption materials /// /// AWS Access Key ID /// AWS Secret Access Key /// The region to connect. /// The encryption materials to be used to encrypt and decrypt envelope key. public AmazonS3EncryptionClient(string awsAccessKeyId, string awsSecretAccessKey, RegionEndpoint region, EncryptionMaterials materials) : base(awsAccessKeyId, awsSecretAccessKey, region) { this.EncryptionMaterials = materials; S3CryptoConfig = new AmazonS3CryptoConfiguration(); } /// /// Constructs AmazonS3EncryptionClient with AWS Access Key ID, Secret Key, /// AmazonS3 CryptoConfiguration object and Encryption materials. /// /// AWS Access Key ID /// AWS Secret Access Key /// The AmazonS3EncryptionClient CryptoConfiguration Object /// The encryption materials to be used to encrypt and decrypt envelope key. public AmazonS3EncryptionClient(string awsAccessKeyId, string awsSecretAccessKey, AmazonS3CryptoConfiguration config, EncryptionMaterials materials) : base(awsAccessKeyId, awsSecretAccessKey, config) { this.EncryptionMaterials = materials; S3CryptoConfig = config; } /// /// Constructs AmazonS3EncryptionClient with AWS Access Key ID, Secret Key, /// SessionToken and Encryption materials. /// /// AWS Access Key ID /// AWS Secret Access Key /// AWS Session Token /// /// The encryption materials to be used to encrypt and decrypt envelope key. /// public AmazonS3EncryptionClient(string awsAccessKeyId, string awsSecretAccessKey, string awsSessionToken, EncryptionMaterials materials) : base(awsAccessKeyId, awsSecretAccessKey, awsSessionToken) { this.EncryptionMaterials = materials; S3CryptoConfig = new AmazonS3CryptoConfiguration(); } /// /// Constructs AmazonS3EncryptionClient with AWS Access Key ID, Secret Key, /// SessionToken, Region and Encryption materials. /// /// AWS Access Key ID /// AWS Secret Access Key /// AWS Session Token /// The region to connect. /// The encryption materials to be used to encrypt and decrypt envelope key. public AmazonS3EncryptionClient(string awsAccessKeyId, string awsSecretAccessKey, string awsSessionToken, RegionEndpoint region, EncryptionMaterials materials) : base(awsAccessKeyId, awsSecretAccessKey, awsSessionToken, region) { this.EncryptionMaterials = materials; S3CryptoConfig = new AmazonS3CryptoConfiguration(); } /// /// Constructs AmazonS3EncryptionClient with AWS Access Key ID, Secret Key, SessionToken /// AmazonS3EncryptionClient CryptoConfiguration object and Encryption materials. /// /// AWS Access Key ID /// AWS Secret Access Key /// AWS Session Token /// The AmazonS3EncryptionClient CryptoConfiguration Object /// /// The encryption materials to be used to encrypt and decrypt envelope key. /// public AmazonS3EncryptionClient(string awsAccessKeyId, string awsSecretAccessKey, string awsSessionToken, AmazonS3CryptoConfiguration config, EncryptionMaterials materials) : base(awsAccessKeyId, awsSecretAccessKey, awsSessionToken, config) { this.EncryptionMaterials = materials; S3CryptoConfig = config; } #endregion /// /// Turn off response logging because it will interfere with decrypt of the data coming back from S3. /// protected override bool SupportResponseLogging { get { return false; } } /// /// Customize the pipeline to allow encryption. /// /// protected override void CustomizeRuntimePipeline(RuntimePipeline pipeline) { base.CustomizeRuntimePipeline(pipeline); pipeline.AddHandlerBefore(new Amazon.S3.Encryption.Internal.SetupEncryptionHandler(this)); pipeline.AddHandlerAfter(new Amazon.S3.Encryption.Internal.UserAgentHandler()); pipeline.AddHandlerBefore(new Amazon.S3.Encryption.Internal.SetupDecryptionHandler(this)); } /// /// Dispose this instance /// /// protected override void Dispose(bool disposing) { lock (kmsClientLock) { if (kmsClient != null) { kmsClient.Dispose(); kmsClient = null; } } base.Dispose(disposing); } } }