- Added ApiClientModel and ApiTokenModel for managing API clients and tokens. - Introduced ConfigurationDefinitionModel and ConfigurationValueModel for configuration management. - Created CredentialSecretModel for storing credential secrets. - Developed DeploymentArtifactModel and DeploymentBatchModel for deployment management. - Enhanced DeploymentTargetModel and DeploymentTemplateSelectionModel to support template revisions. - Added TemplateRevisionModel and TemplateVersionModel for versioning templates. - Implemented ApiClientSecretHasher for secure secret hashing. - Created ApiTokenService for generating and validating JWT tokens. - Updated QueueJobService to handle deployment requests with artifacts. - Configured authentication settings in appsettings.json for JWT and Negotiate authentication.
144 lines
5.1 KiB
C#
144 lines
5.1 KiB
C#
using AutoMapper;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.SelfService.Portal.Core.API.Context;
|
|
using Microsoft.SelfService.Portal.Core.API.Dto.CredentialSecret.Add;
|
|
using Microsoft.SelfService.Portal.Core.API.Dto.CredentialSecret.Get;
|
|
using Microsoft.SelfService.Portal.Core.API.JsonDocuments;
|
|
using Microsoft.SelfService.Portal.Core.API.Models;
|
|
|
|
namespace Microsoft.SelfService.Portal.Core.API.Controllers
|
|
{
|
|
[Route("api/credential-secrets")]
|
|
[ApiController]
|
|
public class CredentialSecretController : Controller
|
|
{
|
|
private readonly DataContext _context;
|
|
private readonly IMapper _mapper;
|
|
|
|
public CredentialSecretController(DataContext context, IMapper mapper)
|
|
{
|
|
_context = context;
|
|
_mapper = mapper;
|
|
}
|
|
|
|
[HttpGet]
|
|
[ProducesResponseType(200, Type = typeof(IEnumerable<GetCredentialSecretDto>))]
|
|
public IActionResult GetCredentialSecrets()
|
|
{
|
|
var secrets = _context.CredentialSecrets
|
|
.AsNoTracking()
|
|
.OrderBy(secret => secret.Name)
|
|
.ToList();
|
|
|
|
return Ok(_mapper.Map<List<GetCredentialSecretDto>>(secrets));
|
|
}
|
|
|
|
[HttpGet("{id}")]
|
|
[ProducesResponseType(200, Type = typeof(GetCredentialSecretDto))]
|
|
[ProducesResponseType(404)]
|
|
public IActionResult GetCredentialSecretById(Guid id)
|
|
{
|
|
var secret = _context.CredentialSecrets
|
|
.AsNoTracking()
|
|
.FirstOrDefault(existing => existing.Id == id);
|
|
|
|
if (secret == null)
|
|
return NotFound();
|
|
|
|
return Ok(_mapper.Map<GetCredentialSecretDto>(secret));
|
|
}
|
|
|
|
[HttpGet("resolve")]
|
|
[ProducesResponseType(200, Type = typeof(GetCredentialSecretValueDto))]
|
|
[ProducesResponseType(404)]
|
|
public IActionResult ResolveCredentialSecret([FromQuery] string name)
|
|
{
|
|
var secret = _context.CredentialSecrets
|
|
.AsNoTracking()
|
|
.FirstOrDefault(existing => existing.Name == name && existing.IsEnabled);
|
|
|
|
if (secret == null)
|
|
return NotFound();
|
|
|
|
return Ok(_mapper.Map<GetCredentialSecretValueDto>(secret));
|
|
}
|
|
|
|
[HttpPost]
|
|
[ProducesResponseType(200, Type = typeof(Guid))]
|
|
[ProducesResponseType(400)]
|
|
public IActionResult AddCredentialSecret([FromBody] AddCredentialSecretDto credentialSecret)
|
|
{
|
|
if (credentialSecret == null)
|
|
return BadRequest(ModelState);
|
|
|
|
if (_context.CredentialSecrets.Any(existing => existing.Name == credentialSecret.Name))
|
|
{
|
|
ModelState.AddModelError(nameof(credentialSecret.Name), "Credential secret already exists.");
|
|
return StatusCode(422, ModelState);
|
|
}
|
|
|
|
if (!string.IsNullOrWhiteSpace(credentialSecret.MetadataJson))
|
|
{
|
|
try
|
|
{
|
|
credentialSecret.MetadataJson = ConfigurationDocumentValidator.NormalizeAndValidate(
|
|
credentialSecret.MetadataJson,
|
|
ConfigurationDocumentKind.Metadata).JsonData;
|
|
}
|
|
catch (ConfigurationDocumentValidationException ex)
|
|
{
|
|
ModelState.AddModelError(nameof(credentialSecret.MetadataJson), ex.Message);
|
|
return BadRequest(ModelState);
|
|
}
|
|
}
|
|
|
|
var model = _mapper.Map<CredentialSecretModel>(credentialSecret);
|
|
model.Id = Guid.NewGuid();
|
|
|
|
_context.CredentialSecrets.Add(model);
|
|
_context.SaveChanges();
|
|
|
|
return Ok(model.Id);
|
|
}
|
|
|
|
[HttpPut("{id}")]
|
|
[ProducesResponseType(204)]
|
|
[ProducesResponseType(404)]
|
|
public IActionResult UpdateCredentialSecret(Guid id, [FromBody] AddCredentialSecretDto credentialSecret)
|
|
{
|
|
var existing = _context.CredentialSecrets.FirstOrDefault(secret => secret.Id == id);
|
|
if (existing == null)
|
|
return NotFound();
|
|
|
|
existing.Name = credentialSecret.Name;
|
|
existing.UserName = credentialSecret.UserName;
|
|
existing.SecretValue = credentialSecret.SecretValue;
|
|
existing.SecretType = credentialSecret.SecretType;
|
|
existing.MetadataJson = credentialSecret.MetadataJson;
|
|
existing.IsEnabled = credentialSecret.IsEnabled;
|
|
existing.Modified = DateTime.UtcNow;
|
|
existing.ModifiedBy = User?.Identity?.Name ?? "System";
|
|
|
|
_context.SaveChanges();
|
|
|
|
return NoContent();
|
|
}
|
|
|
|
[HttpDelete("{id}")]
|
|
[ProducesResponseType(204)]
|
|
[ProducesResponseType(404)]
|
|
public IActionResult DeleteCredentialSecret(Guid id)
|
|
{
|
|
var secret = _context.CredentialSecrets.FirstOrDefault(existing => existing.Id == id);
|
|
if (secret == null)
|
|
return NotFound();
|
|
|
|
_context.CredentialSecrets.Remove(secret);
|
|
_context.SaveChanges();
|
|
|
|
return NoContent();
|
|
}
|
|
}
|
|
}
|