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>()); }
/// <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>()); }
/// <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>())); }
public RegistryCredentialOutputModel(UserTenantRegistryMap map) { Id = map.Registry.Id; Name = map.Registry.Name; ServiceType = map.Registry.ServiceType; UserName = map.RegistryUserName; Password = map.RegistryPassword; }
/// <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); } }
/// <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)); }
/// <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)); }
/// <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)); } }
/// <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)); }
/// <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}\""); }
/// <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)); } }
/// <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})")); } }
/// <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); } }
/// <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)); } }
/// <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)); }
/// <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); }
/// <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); }