/* * MinIO .NET Library for Amazon S3 Compatible Cloud Storage, * (C) 2021 MinIO, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License 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 System.Text; using Minio.DataModel; using Minio.DataModel.Result; using Minio.Exceptions; using Minio.Helper; namespace Minio.Credentials; public class AssumeRoleProvider : AssumeRoleBaseProvider { private readonly string assumeRole = "AssumeRole"; private readonly uint defaultDurationInSeconds = 3600; public AssumeRoleProvider() { } public AssumeRoleProvider(IMinioClient client) : base(client) { } internal string STSEndPoint { get; set; } internal string Url { get; set; } public AssumeRoleProvider WithSTSEndpoint(string endpoint) { if (string.IsNullOrWhiteSpace(endpoint)) throw new ArgumentNullException(nameof(endpoint), "The STS endpoint cannot be null or empty."); STSEndPoint = endpoint; var stsUri = Utils.GetBaseUrl(endpoint); if ((string.Equals(stsUri.Scheme, "http", StringComparison.OrdinalIgnoreCase) && stsUri.Port == 80) || (string.Equals(stsUri.Scheme, "https", StringComparison.OrdinalIgnoreCase) && stsUri.Port == 443) || stsUri.Port <= 0) Url = stsUri.Scheme + "://" + stsUri.Authority; else if (stsUri.Port > 0) Url = stsUri.Scheme + "://" + stsUri.Host + ":" + stsUri.Port; Url = stsUri.Authority; return this; } public override async ValueTask GetCredentialsAsync() { if (Credentials?.AreExpired() == false) return Credentials; var requestBuilder = await BuildRequest().ConfigureAwait(false); if (Client is not null) { ResponseResult responseResult = null; try { responseResult = await Client.ExecuteTaskAsync(NoErrorHandlers, requestBuilder, true) .ConfigureAwait(false); AssumeRoleResponse assumeRoleResp = null; if (responseResult.Response.IsSuccessStatusCode) { using var stream = new MemoryStream(Encoding.UTF8.GetBytes(responseResult.Content).AsMemory().ToArray()); assumeRoleResp = Utils.DeserializeXml(stream); } if (Credentials is null && assumeRoleResp?.AssumeRole is not null) Credentials = assumeRoleResp.AssumeRole.Credentials; return Credentials; } finally { responseResult?.Dispose(); } } throw new InternalClientException("Client should have been assigned for the operation to continue."); } internal override async Task BuildRequest() { Action = assumeRole; if (DurationInSeconds is null || DurationInSeconds.Value == 0) DurationInSeconds = defaultDurationInSeconds; var requestMessageBuilder = await Client.CreateRequest(HttpMethod.Post).ConfigureAwait(false); using var formContent = new FormUrlEncodedContent(new[] { new KeyValuePair("Action", "AssumeRole"), new KeyValuePair("DurationSeconds", DurationInSeconds.ToString()), new KeyValuePair("Version", "2011-06-15") }); ReadOnlyMemory byteArrContent = await formContent.ReadAsByteArrayAsync().ConfigureAwait(false); requestMessageBuilder.SetBody(byteArrContent); requestMessageBuilder.AddOrUpdateHeaderParameter("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"); requestMessageBuilder.AddOrUpdateHeaderParameter("Accept-Encoding", "identity"); await Task.Yield(); return requestMessageBuilder; } }