1

我正在尝试从各种容器映像注册表中获取映像清单信息。为了进行身份验证,我已经通过 Docker 实现了令牌规范(https://docs.docker.com/registry/spec/auth/token/),它似乎正在与 Docker Hub(公共和私有存储库)、Azure容器注册服务和谷歌容器注册服务。AWS Elastic Container Registry Service 似乎需要对 GetAuthorizationToken API 进行额外调用,该 API 返回要在基本 Http 身份验证中使用的用户名和密码。我的理解是否正确(根据 Docker 令牌规范)我无法使用固定的用户名和密码对,然后使用 WWW-Authenticate 质询标头我可以获得不记名令牌来获取访问令牌?

我现在面临的挑战是,我需要根据它是 AWS ECR 还是其他注册表服务来对我的代码进行特殊情况下的身份验证。

到目前为止我的 C# 代码:

class Program
{
    internal sealed class BearerToken
    {
        public string token;
        public string access_token;
        public string scope;
        public string expires_in;
        public string issued_at;
        public string refresh_token;
    }

    private static HttpClient httpClient = new HttpClient()
    {
        Timeout = TimeSpan.FromSeconds(100)
    };

    static void Main(string[] args)
    {
        string imagename = "hello-world:latest";
        Uri manifestUri = new Uri("https://619296171463.dkr.ecr.us-east-2.amazonaws.com/v2/hello-world/manifests/latest");

        // aws access key id
        //string username = "AWSACCESSKEYID";

        // aws secret access key
        //string password = "AWSSECRETACCESSKEY";

        // aws ecr get-login output
        string username = "AWS";
        string password = "24HRSLONGPASSWORDSTRING";

        HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, manifestUri);
        requestMessage.Headers.Add("Accept", "application/vnd.docker.distribution.manifest.v2+json");

        HttpResponseMessage responseMessage = httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseContentRead, CancellationToken.None).GetAwaiter().GetResult();

        if (responseMessage.StatusCode == HttpStatusCode.Unauthorized)
        {
            /*string authorizationHeaderChallenge = responseMessage.Headers.WwwAuthenticate.ToString();
            string[] challengeItems = authorizationHeaderChallenge.Split(new char[] { ' ' }, 2);
            string authScheme = challengeItems[0];
            string authParamFormat = @"(?<key>\w+)=([""'])(?<value>.*)([""'])";
            Regex authParamRegEx = new Regex(authParamFormat);
            var authParamsItems = challengeItems[1].Split(',');
            Dictionary<string, string> authParams = new Dictionary<string, string>();
            foreach (var authParam in authParamsItems)
            {
                var match = authParamRegEx.Match(authParam);
                authParams[match.Groups["key"].Value] = match.Groups["value"].Value;
            }

            UriBuilder uriBuilder = new UriBuilder($"{authParams["realm"]}");
            //string query = $"{"scope"}={"repository:containerimageinfoproject/demo-image:pull"}&{ "service"}={authParams["service"]}";
            string query = $"{"service"}={authParams["service"]}";
            uriBuilder.Query = query;

            Uri authorizationEndPoint = uriBuilder.Uri;*/

            string authenticationTokenValue = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{username}:{password}"));

            requestMessage = new HttpRequestMessage(HttpMethod.Get, manifestUri);
            requestMessage.Headers.Authorization =
                new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", authenticationTokenValue);

            responseMessage = httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseContentRead, CancellationToken.None).GetAwaiter().GetResult();

            string response = responseMessage.Content.ReadAsStringAsync().GetAwaiter().GetResult();

            /*BearerToken bearerToken = JsonConvert.DeserializeObject<BearerToken>(response);

            requestMessage = new HttpRequestMessage(HttpMethod.Get, manifestUri);
            requestMessage.Headers.Add("Accept", "application/vnd.docker.distribution.manifest.v2+json");
            requestMessage.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", bearerToken.token);

            responseMessage = httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseContentRead, CancellationToken.None).GetAwaiter().GetResult();*/
        }
    }
}

在这里,如果我使用 (username, password) = (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY) 那么我会不断得到:

{StatusCode:401,ReasonPhrase:'未授权',版本:1.1,内容:System.Net.Http.StreamContent,标头:{ Docker-Distribution-Api-Version:registry/2.0 连接:keep-alive 日期:星期三,8 月 1 日2018 年 21:40:37 GMT WWW-Authenticate: Basic realm="https://619296171463.dkr.ecr.us-east-2.amazonaws.com/",service="ecr.amazonaws.com" 内容长度: 15 内容类型:文本/纯文本;字符集=utf-8 }}

而如果我使用 (username, password) = ("AWS", "LONGPASSWORD_GENERATED_USING_AWS_ECR_GETLOGIN"),我可以获得图像清单。

4

0 回答 0