private async Task <Result <string, string> > GetAuthTokenAsync(UserTenantRegistryMap userRegistryMap, string imageName)
        {
            string scope = $"repository:{imageName}:pull";

            // API呼び出しパラメータ作成
            RequestParam param = new RequestParam()
            {
                BaseUrl     = "https://auth.docker.io/",
                ApiPath     = $"/token",
                UserName    = userRegistryMap.RegistryUserName,
                Password    = userRegistryMap.RegistryPassword,
                QueryParams = new Dictionary <string, string>
                {
                    { "service", "registry.docker.io" },
                    { "scope", $"repository:{imageName}:pull" },
                    //{ "offline_token", "true" }
                }
            };

            // API 呼び出し
            var response = await this.SendGetRequestAsync(param);

            if (response.IsSuccess)
            {
                var tokenModel = ConvertResult <GetAuthTokenApiModel>(response);
                return(Result <string, string> .CreateResult(tokenModel.Token));
            }
            else
            {
                LogError("認証トークンの取得に失敗:" + response.Error);
                return(Result <string, string> .CreateErrorResult(response.Error));
            }
        }
        /// <summary>
        /// 全てのイメージのリストを取得
        /// </summary>
        /// <param name="userRegistryMap">ユーザとレジストリのマッピング情報</param>
        /// <returns>全イメージのリスト。エラーの場合はNULL。</returns>
        public async Task <List <string> > GetAllImageListAsync(UserTenantRegistryMap userRegistryMap)
        {
            await Task.CompletedTask;

            // DockerHubはAPIを公開していない。
            // そのため必ず空のリストを返す。
            return(new List <string>());
        }
Пример #3
0
        /// <summary>
        /// 全てのイメージのリストを取得
        /// </summary>
        /// <param name="userRegistryMap">ユーザとレジストリのマッピング情報</param>
        /// <returns>全イメージのリスト。エラーの場合はNULL。</returns>
        public async Task <List <string> > GetAllImageListAsync(UserTenantRegistryMap userRegistryMap)
        {
            await Task.CompletedTask;

            // NGCはユーザに手入力で設定させる。
            // そのため必ず空のリストを返す。
            return(new List <string>());
        }
Пример #4
0
        /// <summary>
        /// 指定されたイメージのタグを取得
        /// </summary>
        /// <param name="userRegistryMap">ユーザとレジストリのマッピング情報</param>
        /// <param name="imageName">イメージ名</param>
        /// <returns>タグのリスト</returns>
        public async Task <Result <List <string>, string> > GetAllTagListAsync(UserTenantRegistryMap userRegistryMap, string imageName)
        {
            await Task.CompletedTask;

            // NGCはユーザに手入力で設定させる。
            // そのため必ず空のリストを返す。
            return(Result <List <string>, string> .CreateResult(new List <string>()));
        }
Пример #5
0
 public RegistryCredentialOutputModel(UserTenantRegistryMap map)
 {
     Id          = map.Registry.Id;
     Name        = map.Registry.Name;
     ServiceType = map.Registry.ServiceType;
     UserName    = map.RegistryUserName;
     Password    = map.RegistryPassword;
 }
Пример #6
0
        /// <summary>
        /// 全てのイメージのリストを取得
        /// </summary>
        /// <param name="userRegistryMap">ユーザとレジストリのマッピング情報</param>
        /// <returns>全イメージのリスト。エラーの場合はNULL。</returns>
        public async Task <List <string> > GetAllImageListAsync(UserTenantRegistryMap userRegistryMap)
        {
            var images = await GetContainerRegistryJsonAsync(userRegistryMap.Registry, userRegistryMap.Registry.ProjectName, userRegistryMap.RegistryPassword);

            if (images != null)
            {
                //イメージのPathにはリポジトリ名も入ってしまっているが、GitLabだとイメージ名が空(/owner/repos:tagの形式)が許されているので、trimせずにそのまま返す
                return(images.Select(i => i.Path).ToList());
            }
            else
            {
                return(null);
            }
        }
Пример #7
0
        /// <summary>
        /// クラスタ管理サービスに登録するdockercfgを作る。
        /// エラーが発生したらnullが返る。
        /// <see cref="ServiceModels.ClusterManagementModels.RegistRegistryTokenInputModel.DockerCfgAuthString"/>に格納される。
        /// </summary>
        public string GetDockerCfgAuthString(UserTenantRegistryMap userRegistryMap)
        {
            //GitLabではtokenはパスワードとして管理されている
            string userName = userRegistryMap.RegistryUserName;
            string password = userRegistryMap.RegistryPassword;

            if (string.IsNullOrEmpty(password))
            {
                LogWarning($"User {userRegistryMap.UserId}'s token is empty. UserTenantRegistryMapID = {userRegistryMap.Id}");
                return(null);
            }

            return(GetDockerCfgAuthString(userName, password));
        }
Пример #8
0
        /// <summary>
        /// クラスタ管理サービスに登録するdockercfgを作る。
        /// エラーが発生したらnullが返る。
        /// <see cref="ServiceModels.ClusterManagementModels.RegistRegistryTokenInputModel.DockerCfgAuthString"/>に格納される。
        /// </summary>
        public string GetDockerCfgAuthString(UserTenantRegistryMap userRegistryMap)
        {
            //ユーザ名
            string userName = "******";

            //API Key
            string password = userRegistryMap.RegistryPassword;

            if (string.IsNullOrEmpty(password))
            {
                LogWarning($"User {userRegistryMap.UserId}'s password is empty. UserTenantRegistryMapID = {userRegistryMap.Id}");
                return(null);
            }
            return(GetDockerCfgAuthString(UserName, password));
        }
Пример #9
0
        /// <summary>
        /// クラスタ管理サービスに登録するdockercfgを作る。
        /// エラーが発生したらnullが返る。
        /// <see cref="ServiceModels.ClusterManagementModels.RegistRegistryTokenInputModel.DockerCfgAuthString"/>に格納される。
        /// </summary>
        public string GetDockerCfgAuthString(UserTenantRegistryMap userRegistryMap)
        {
            Registry         registry        = userRegistryMap.Registry;
            IRegistryService registryService = GetRegistryService(registry);

            if (registryService != null)
            {
                return(registryService.GetDockerCfgAuthString(userRegistryMap));
            }
            else
            {
                LogError($"Undefined registry: {registry.Name}({registry.ServiceType})");
                return(null);
            }
        }
        /// <summary>
        /// 指定されたイメージのタグを取得
        /// </summary>
        /// <param name="userRegistryMap">ユーザとレジストリのマッピング情報</param>
        /// <param name="imageName">イメージ名</param>
        /// <returns>タグのリスト</returns>
        public async Task <Result <List <string>, string> > GetAllTagListAsync(UserTenantRegistryMap userRegistryMap, string imageName)
        {
            if (string.IsNullOrEmpty(userRegistryMap.RegistryPassword))
            {
                //DockerHubの場合、ユーザ名・パスワードが必須なので、未入力だったら空を返すs
                return(Result <List <string>, string> .CreateResult(new List <string>()));
            }

            string token;

            if (string.IsNullOrEmpty(userRegistryMap.RegistryUserName))
            {
                //ユーザ名が未設定の場合、パスワードにトークンが入っているとみなす
                token = userRegistryMap.RegistryPassword;
            }
            else
            {
                //トークンではなく、ユーザ名・パスワードが指定されている場合、まずはOAuthトークンを取得する
                var tokenResult = await GetAuthTokenAsync(userRegistryMap, imageName);

                if (tokenResult.IsSuccess == false)
                {
                    return(Result <List <string>, string> .CreateErrorResult(tokenResult.Error));
                }
                token = tokenResult.Value;
            }

            // API呼び出しパラメータ作成
            RequestParam param = new RequestParam()
            {
                BaseUrl = userRegistryMap.Registry.ApiUrl,
                ApiPath = $"/v2/{imageName}/tags/list",
                Token   = token
            };

            // API 呼び出し
            var response = await this.SendGetRequestAsync(param);

            if (response.IsSuccess)
            {
                var images = ConvertResult <GetTagsApiModel>(response).Tags;
                return(Result <List <string>, string> .CreateResult(images));
            }
            else
            {
                return(Result <List <string>, string> .CreateErrorResult(response.Error));
            }
        }
Пример #11
0
        /// <summary>
        /// クラスタ管理サービスに登録するdockercfgを作る。
        /// エラーが発生したらnullが返る。
        /// <see cref="ServiceModels.ClusterManagementModels.RegistRegistryTokenInputModel.DockerCfgAuthString"/>に格納される。
        /// </summary>
        public string GetDockerCfgAuthString(UserTenantRegistryMap userRegistryMap)
        {
            //ユーザ名
            string userName = "******";

            //API Key
            string password = userRegistryMap.RegistryPassword;

            if (string.IsNullOrEmpty(password))
            {
                LogWarning($"User {userRegistryMap.UserId}'s password is empty. UserTenantRegistryMapID = {userRegistryMap.Id}");
                return(null);
            }
            var auth = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{userName}:{password}"));

            return($"\"username\":\"{userName}\",\"password\":\"{password}\",\"auth\":\"{auth}\"");
        }
        /// <summary>
        /// クラスタ管理サービスに登録するdockercfgを作る。
        /// エラーが発生したらnullが返る。
        /// <see cref="ServiceModels.ClusterManagementModels.RegistRegistryTokenInputModel.DockerCfgAuthString"/>に格納される。
        /// </summary>
        public string GetDockerCfgAuthString(UserTenantRegistryMap userRegistryMap)
        {
            string userName = userRegistryMap.RegistryUserName;

            if (string.IsNullOrEmpty(userName))
            {
                LogWarning($"User {userRegistryMap.UserId}'s userName is empty. UserTenantRegistryMapID = {userRegistryMap.Id}");
                return(null);
            }
            string password = userRegistryMap.RegistryPassword;

            if (string.IsNullOrEmpty(password))
            {
                LogWarning($"User {userRegistryMap.UserId}'s password is empty. UserTenantRegistryMapID = {userRegistryMap.Id}");
                return(null);
            }
            return(GetDockerCfgAuthString(userName, password));
        }
Пример #13
0
        /// <summary>
        /// クラスタ管理サービスに登録するdockercfgを作る。
        /// エラーが発生したらnullが返る。
        /// <see cref="ServiceModels.ClusterManagementModels.RegistRegistryTokenInputModel.DockerCfgAuthString"/>に格納される。
        /// </summary>
        public string GetDockerCfgAuthString(UserTenantRegistryMap userRegistryMap)
        {
            //GitLabではtokenはパスワードとして管理されている
            string token = userRegistryMap.RegistryPassword;

            if (string.IsNullOrEmpty(token))
            {
                LogWarning($"User {userRegistryMap.UserId}'s token is empty. UserTenantRegistryMapID = {userRegistryMap.Id}");
                return(null);
            }

            //GitLabの場合、トークンを使うならuserNameは任意の文字列(空文字除く)を与えられる。
            //なのでダミー文字列としてkqiを入れる。
            //ユーザ名はシークレット名にも使われるので、ここでは扱わない
            var auth = Convert.ToBase64String(Encoding.UTF8.GetBytes($"kqi:{token}"));

            return($"\"auth\":\"{auth}\"");
        }
Пример #14
0
        /// <summary>
        /// 指定されたイメージのタグを取得
        /// </summary>
        /// <param name="userRegistryMap">ユーザとレジストリのマッピング情報</param>
        /// <param name="imageName">イメージ名</param>
        /// <returns>タグのリスト</returns>
        public async Task <Result <List <string>, string> > GetAllTagListAsync(UserTenantRegistryMap userRegistryMap, string imageName)
        {
            Registry registry = userRegistryMap.Registry;
            var      images   = await GetContainerRegistryJsonAsync(registry, userRegistryMap.Registry.ProjectName, userRegistryMap.RegistryPassword);

            if (images == null)
            {
                return(Result <List <string>, string> .CreateErrorResult("Failed to get image info."));
            }
            var image = images.FirstOrDefault(i => i.Path == imageName);

            if (image == null)
            {
                return(Result <List <string>, string> .CreateErrorResult($"Image {imageName} is not Found."));
            }

            // API呼び出しパラメータ作成
            string       encodedProjectName = userRegistryMap.Registry.ProjectName.Replace("/", "%2F");
            RequestParam param = new RequestParam()
            {
                BaseUrl = registry.ApiUrl,
                ApiPath = $"api/v4/projects/{encodedProjectName}/registry/repositories/{image.Id}/tags",
                Headers = new Dictionary <string, string>()
                {
                    { "PRIVATE-TOKEN", userRegistryMap.RegistryPassword } //GitLabはトークンの形式がBearerではないので、ヘッダに独自で追加
                }
            };

            // API 呼び出し
            var response = await this.SendGetRequestAsync(param);

            if (response.IsSuccess)
            {
                var tags = ConvertResult <IEnumerable <GetTagsApiModel> >(response);
                return(Result <List <string>, string> .CreateResult(tags.Select(t => t.Name).ToList()));
            }
            else
            {
                return(Result <List <string>, string> .CreateErrorResult(response.Error));
            }
        }
Пример #15
0
        /// <summary>
        /// 指定されたイメージのタグを取得
        /// </summary>
        /// <param name="registryId">レジストリID</param>
        /// <param name="imageName">イメージ名</param>
        /// <returns>タグのリスト</returns>
        public async Task <Result <List <string>, string> > GetAllTagListAsync(long registryId, string imageName)
        {
            UserTenantRegistryMap registryMap = GetCurrentRegistryMap(registryId);

            if (registryMap == null)
            {
                return(Result <List <string>, string> .CreateErrorResult($"registry {registryId} does NOT map to the current user"));
            }
            Registry         registry        = registryMap.Registry;
            IRegistryService registryService = GetRegistryService(registry);

            if (registry != null)
            {
                string image = imageName.StartsWith("/") ? imageName.Substring(1) : imageName;
                return(await registryService.GetAllTagListAsync(registryMap, image));
            }
            else
            {
                return(Result <List <string>, string> .CreateErrorResult($"undefined registry: {registry.Name}({registry.ServiceType})"));
            }
        }
Пример #16
0
        /// <summary>
        /// 全てのイメージのリストを取得
        /// </summary>
        /// <returns>全イメージのリスト。エラーの場合はNULL。</returns>
        public async Task <List <string> > GetAllImageListAsync(long registryId)
        {
            UserTenantRegistryMap registryMap = GetCurrentRegistryMap(registryId);

            if (registryMap == null)
            {
                LogError($"registry {registryId} does NOT map to the current user");
                return(null);
            }
            Registry         registry        = registryMap.Registry;
            IRegistryService registryService = GetRegistryService(registry);

            if (registryService != null)
            {
                return(await registryService.GetAllImageListAsync(registryMap));
            }
            else
            {
                LogError($"Undefined registry: {registry.Name}({registry.ServiceType})");
                return(null);
            }
        }
Пример #17
0
        /// <summary>
        /// 指定されたイメージのタグを取得
        /// </summary>
        /// <param name="userRegistryMap">ユーザとレジストリのマッピング情報</param>
        /// <param name="imageName">イメージ名</param>
        /// <returns>タグのリスト</returns>
        public async Task <Result <List <string>, string> > GetAllTagListAsync(UserTenantRegistryMap userRegistryMap, string imageName)
        {
            // API呼び出しパラメータ作成
            RequestParam param = new RequestParam()
            {
                BaseUrl  = userRegistryMap.Registry.ApiUrl,
                ApiPath  = $"/v2/{imageName}/tags/list",
                UserName = userRegistryMap.RegistryUserName,
                Password = userRegistryMap.RegistryPassword
            };

            // API 呼び出し
            var response = await this.SendGetRequestAsync(param);

            if (response.IsSuccess)
            {
                var images = ConvertResult <GetTagsApiModel>(response).Tags;
                return(Result <List <string>, string> .CreateResult(images));
            }
            else
            {
                return(Result <List <string>, string> .CreateErrorResult(response.Error));
            }
        }
Пример #18
0
        /// <summary>
        /// 全てのイメージのリストを取得
        /// </summary>
        /// <param name="userRegistryMap">ユーザとレジストリのマッピング情報</param>
        /// <returns>全イメージのリスト。エラーの場合はNULL。</returns>
        public async Task <List <string> > GetAllImageListAsync(UserTenantRegistryMap userRegistryMap)
        {
            // API呼び出しパラメータ作成
            RequestParam param = new RequestParam()
            {
                BaseUrl  = userRegistryMap.Registry.ApiUrl,
                ApiPath  = $"/v2/_catalog",
                UserName = userRegistryMap.RegistryUserName,
                Password = userRegistryMap.RegistryPassword
            };
            // API 呼び出し
            var response = await this.SendGetRequestAsync(param);

            if (response.IsSuccess)
            {
                var images = ConvertResult <GetImagesApiModel>(response).Repositories;
                return(images);
            }
            else
            {
                LogError("イメージ一覧の取得に失敗:" + response.Error);
                return(null);
            }
        }
        /// <summary>
        /// クラスタ管理サービス上で、指定したユーザ&テナントにコンテナレジストリを登録する。
        /// idempotentを担保。
        /// </summary>
        public async Task <bool> RegistRegistryToTenantAsync(string selectedTenantName, UserTenantRegistryMap userRegistryMap)
        {
            if (userRegistryMap == null)
            {
                return(false);
            }
            //初回登録時など、まだパスワードが設定されていなかったら、登録はしない。
            if (string.IsNullOrEmpty(userRegistryMap.RegistryPassword))
            {
                return(true); //正常系扱い
            }
            string dockerCfg = registryLogic.GetDockerCfgAuthString(userRegistryMap);

            if (dockerCfg == null)
            {
                return(false);
            }
            var inModel = new RegistRegistryTokenInputModel()
            {
                TenantName          = selectedTenantName,
                RegistryTokenKey    = userRegistryMap.RegistryTokenKey,
                DockerCfgAuthString = dockerCfg,
                Url = userRegistryMap.Registry.RegistryUrl
            };

            return(await clusterManagementService.RegistRegistryTokenyAsync(inModel));
        }
Пример #20
0
        /// <summary>
        /// ユーザをテナントに所属させる。
        /// ユーザIDやテナントIDの存在チェックは行わない。
        /// 結果として、作成したすべての<see cref="UserTenantRegistryMap"/>を返す。
        /// </summary>
        /// <param name="user">対象ユーザ</param>
        /// <param name="tenantId">対象テナントID</param>
        /// <param name="roles">テナントロール</param>
        /// <exception cref="ArgumentException"><paramref name="roles"/>にシステムロールが含まれていたり、別テナント用のロールが含まれていた場合</exception>
        public IEnumerable <UserTenantRegistryMap> AttachTenant(User user, long tenantId, IEnumerable <Role> roles)
        {
            var tenantMap = new UserTenantMap()
            {
                TenantId = tenantId,
                User     = user
            };

            AddModel <UserTenantMap>(tenantMap);
            if (roles != null)
            {
                foreach (var role in roles)
                {
                    if (role == null)
                    {
                        continue;
                    }
                    if (role.IsSystemRole)
                    {
                        //Adminロールを特定テナントに所属させようとしている
                        throw new UnauthorizedAccessException($"The tenant role {role.Name} is not assigned to a user as a system role.");
                    }
                    var roleMap = new UserRoleMap()
                    {
                        RoleId    = role.Id,
                        TenantMap = tenantMap,
                        User      = user
                    };
                    AddModel <UserRoleMap>(roleMap);
                }
            }

            //まずはGitの登録
            //テナントに紐づいているすべてのGitを取得
            var GitMaps = FindModelAll <TenantGitMap>(m => m.TenantId == tenantId).Include(m => m.Git);

            foreach (var GitMap in GitMaps)
            {
                UserTenantGitMap utrMap = new UserTenantGitMap()
                {
                    TenantGitMap = GitMap,
                    UserId       = user.Id
                };

                // 既存の認証情報存在チェック
                var existMap = GetModelAll <UserTenantGitMap>()
                               .Where(m => m.UserId == user.Id && m.TenantGitMapId == GitMap.Id).FirstOrDefault();
                if (existMap != null)
                {
                    // 既存の認証情報が存在する場合、再設定する
                    utrMap.GitToken = existMap.GitToken;
                }
                else
                {
                    // UserTenantGitMap において userId と TenantGitMapId のペアが存在しなければ、エントリ新規追加のためログに出力する
                    LogDebug($"UserTenantGitMap エントリの新規追加 : UserId={user.Id}, TenantGitMapId={GitMap.Id}, TenantId={tenantId}, GitId={GitMap.GitId}");
                }

                AddModel <UserTenantGitMap>(utrMap);
            }

            //続いてレジストリの登録
            //レジストリ登録はクラスタ管理サービスへも影響するので、作成したMapを全て返す

            List <UserTenantRegistryMap> maps = new List <UserTenantRegistryMap>();

            //テナントに紐づいているすべてのレジストリを取得
            var registryMaps = FindModelAll <TenantRegistryMap>(m => m.TenantId == tenantId).Include(m => m.Registry);

            foreach (var registryMap in registryMaps)
            {
                UserTenantRegistryMap utrMap = new UserTenantRegistryMap()
                {
                    TenantRegistryMap = registryMap,
                    UserId            = user.Id
                };

                // 既存の認証情報存在チェック
                var existMap = GetModelAll <UserTenantRegistryMap>()
                               .Where(m => m.UserId == user.Id && m.TenantRegistryMapId == registryMap.Id).FirstOrDefault();
                if (existMap != null)
                {
                    // 既存の認証情報が存在する場合、再設定する
                    utrMap.RegistryUserName = existMap.RegistryUserName;
                    utrMap.RegistryPassword = existMap.RegistryPassword;
                }

                AddModel <UserTenantRegistryMap>(utrMap);
                maps.Add(utrMap);
            }
            return(maps);
        }
Пример #21
0
        /// <summary>
        /// テナントにレジストリを紐づける。
        /// 結果として、作成したすべての<see cref="UserTenantRegistryMap"/>を返す。
        /// テナントの新規作成時であれば、<paramref name="isCreate"/>をTrueにする。
        /// </summary>
        public async Task <IEnumerable <UserTenantRegistryMap> > AttachRegistryToTenantAsync(Tenant tenant, Registry registry, bool isCreate)
        {
            if (registry == null)
            {
                //指定がなければ何もしない
                return(null);
            }

            TenantRegistryMap map = new TenantRegistryMap()
            {
                Registry = registry
            };

            List <UserTenantRegistryMap> maps = null;

            if (isCreate == false) //テナント新規作成時はIDが0の状態なので、判定しない。ユーザも未参加なので何もしない。
            {
                map.TenantId = tenant.Id;

                //既に紐づいていたら何もしない
                bool exist = await ExistsModelAsync <TenantRegistryMap>(m => m.TenantId == tenant.Id && m.RegistryId == registry.Id);

                if (exist)
                {
                    return(null);
                }

                maps = new List <UserTenantRegistryMap>();

                //テナントに紐づいているすべてのユーザを取得
                var userMaps = FindModelAll <UserTenantMap>(m => m.TenantId == tenant.Id);
                foreach (var userMap in userMaps)
                {
                    UserTenantRegistryMap utrMap = new UserTenantRegistryMap()
                    {
                        TenantRegistryMap = map,
                        UserId            = userMap.UserId,
                    };

                    //既に同じレジストリと紐づいていたら、その認証情報を使いまわす
                    var existMap = GetModelAll <UserTenantRegistryMap>().Include(m => m.TenantRegistryMap)
                                   .Where(m => m.UserId == userMap.UserId && m.TenantRegistryMap.RegistryId == registry.Id).FirstOrDefault();
                    if (existMap != null)
                    {
                        utrMap.RegistryUserName = existMap.RegistryUserName;
                        utrMap.RegistryPassword = existMap.RegistryPassword;
                    }
                    else
                    {
                        utrMap.RegistryUserName = registry.ProjectName;
                    }
                    AddModel <UserTenantRegistryMap>(utrMap);
                    maps.Add(utrMap);
                }
            }
            else
            {
                map.Tenant = tenant;
            }

            AddModel <TenantRegistryMap>(map);
            return(maps);
        }