Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

353928: Apply authentication restrictions #66

Merged
merged 2 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .azuredevops/containerApp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ properties:
- name: backstage-authority
keyVaultUrl: https://{{appKeyVaultName}}.vault.azure.net/secrets/BACKSTAGE-AUTHORITY
identity: {{userAssignedIdentity}}
- name: backstage-issuer
- name: api-auth-backend-app-reg-client-id
keyVaultUrl: https://{{appKeyVaultName}}.vault.azure.net/secrets/API-AUTH-BACKEND-APP-REG-CLIENT-ID
identity: {{userAssignedIdentity}}
template:
containers:
- image: {{acrName}}.azurecr.io/image/{{imageRepoName}}:{{appVersion}}
Expand Down Expand Up @@ -118,6 +120,12 @@ properties:
value: false
- name: Authentication__backstage__TokenValidationParameters__ValidateAudience
value: false
- name: Authentication__pipeline__Instance
value: https://login.microsoftonline.com/
- name: Authentication__pipeline__TenantId
value: {{tenantid}}
- name: Authentication__pipeline__ClientId
secretRef: api-auth-backend-app-reg-client-id
resources:
cpu: 0.5
memory: 1Gi
Expand Down
3 changes: 2 additions & 1 deletion src/ADP.Portal.Api/ADP.Portal.Api.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Version>0.2.16</Version>
<Version>0.2.17</Version>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<InvariantGlobalization>true</InvariantGlobalization>
Expand All @@ -20,6 +20,7 @@
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.6" />
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.2" />
<PackageReference Include="Microsoft.Identity.Client" Version="4.61.3" />
<PackageReference Include="Microsoft.Identity.Web" Version="2.19.1" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.20.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
<PackageReference Include="Azure.Monitor.OpenTelemetry.AspNetCore" Version="1.2.0" />
Expand Down
5 changes: 5 additions & 0 deletions src/ADP.Portal.Api/Controllers/AadGroupController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using ADP.Portal.Core.Git.Entities;
using ADP.Portal.Core.Git.Services;
using Asp.Versioning;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;

Expand Down Expand Up @@ -32,6 +33,7 @@ public AadGroupController(IGroupsConfigService groupsConfigService, ILogger<AadG
/// <param name="teamName">Required: Name of the Team, like ffc-demo</param>
/// <returns></returns>
[HttpGet("{teamName}/groups-config", Name = "GetGroupsConfigForTeam")]
[Authorize(AuthenticationSchemes = "")]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult> GetGroupsConfigAsync(string teamName)
{
Expand All @@ -50,6 +52,7 @@ public async Task<ActionResult> GetGroupsConfigAsync(string teamName)
/// <param name="createGroupsConfigRequest">Required: Collection of the users to set up as members in the Admin Group</param>
/// <returns></returns>
[HttpPost("{teamName}/groups-config", Name = "CreateGroupsConfigForTeam")]
[Authorize(AuthenticationSchemes = "backstage")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult> CreateGroupsConfigAsync(string teamName, [FromBody] CreateGroupsConfigRequest createGroupsConfigRequest)
Expand Down Expand Up @@ -82,6 +85,7 @@ public async Task<ActionResult> CreateGroupsConfigAsync(string teamName, [FromBo
}

[HttpPatch("{teamName}/members", Name = "SetMembersForTeam")]
[Authorize(AuthenticationSchemes = "backstage")]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult> SetGroupMembersAsync(string teamName, [FromBody] SetGroupMembersRequest setGroupMembersRequest)
Expand Down Expand Up @@ -119,6 +123,7 @@ public async Task<ActionResult> SetGroupMembersAsync(string teamName, [FromBody]
/// <param name="groupType">Optional: Type of groups to sync i.e. UserGroup/AccessGroup/OpenVpnGroup</param>
/// <returns></returns>
[HttpPut("{teamName}/sync", Name = "SyncGroupsForTeam")]
[Authorize(AuthenticationSchemes = "")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult> SyncGroupsAsync(string teamName, [FromQuery] string? groupType = null)
Expand Down
3 changes: 3 additions & 0 deletions src/ADP.Portal.Api/Controllers/AdoProjectController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using ADP.Portal.Core.Ado.Services;
using Asp.Versioning;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;

Expand Down Expand Up @@ -32,6 +33,7 @@ public AdoProjectController(ILogger<AdoProjectController> logger, IOptions<AdpAd
/// <param name="projectName">Required: Name of the project</param>
/// <returns></returns>
[HttpGet("{projectName}")]
[Authorize(AuthenticationSchemes = "backstage")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<ActionResult> GetAdoProject(string projectName)
Expand All @@ -53,6 +55,7 @@ public async Task<ActionResult> GetAdoProject(string projectName)
/// <param name="onBoardRequest">Required: Details about environments, pools, connections & variable groups</param>
/// <returns></returns>
[HttpPatch("{projectName}/onboard")]
[Authorize(AuthenticationSchemes = "backstage")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(OnboardProjectResult))]
public async Task<ActionResult> OnBoardAsync(string projectName, [FromBody] OnBoardAdoProjectRequest onBoardRequest)
{
Expand Down
2 changes: 2 additions & 0 deletions src/ADP.Portal.Api/Controllers/FluxManifestController.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using ADP.Portal.Api.Models.Flux;
using ADP.Portal.Core.Git.Services;
using Asp.Versioning;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace ADP.Portal.Api.Controllers;
Expand All @@ -26,6 +27,7 @@ public FluxManifestController(IFluxManifestService fluxManifestService, ILogger<
/// <param name="templateType"></param>
/// <returns></returns>
[HttpGet("templates/service/{templateType}/patch-values")]
[AllowAnonymous]
public async Task<ActionResult> GetFluxServiceTemplateManifest([FromRoute] string templateType)
{
if (!Enum.TryParse<ServiceTemplateType>(templateType, true, out var parsedTemplateType))
Expand Down
10 changes: 9 additions & 1 deletion src/ADP.Portal.Api/Controllers/FluxTeamConfigController.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
using ADP.Portal.Api.Config;
using ADP.Portal.Api.Models.Flux;
using Entities = ADP.Portal.Core.Git.Entities;
using ADP.Portal.Core.Git.Services;
using Asp.Versioning;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Entities = ADP.Portal.Core.Git.Entities;

namespace ADP.Portal.Api.Controllers;

Expand All @@ -32,6 +33,7 @@ public FluxTeamConfigController(IFluxTeamConfigService fluxTeamConfigService, IL
/// <param name="teamName">Required: Name of the Team, like ffc-demo</param>
/// <returns></returns>
[HttpGet("{teamName}", Name = "GetFluxConfigForTeam")]
[Authorize(AuthenticationSchemes = "backstage")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<ActionResult> GetConfigAsync(string teamName)
Expand All @@ -54,6 +56,7 @@ public async Task<ActionResult> GetConfigAsync(string teamName)
/// <param name="fluxConfigRequest">Required: Details about the Services, Environments & ConfigVariables for the team</param>
/// <returns></returns>
[HttpPost("{teamName}", Name = "CreateFluxConfigForTeam")]
[Authorize(AuthenticationSchemes = "backstage")]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult> CreateConfigAsync(string teamName, [FromBody] TeamConfigRequest fluxConfigRequest)
Expand All @@ -78,6 +81,7 @@ public async Task<ActionResult> CreateConfigAsync(string teamName, [FromBody] Te
/// <param name="serviceFluxConfigRequest">The request object containing all the necessary information to create a new service in the Flux Config.</param>
/// <returns></returns>
[HttpPost("{teamName}/services", Name = "CreateServiceFluxConfigForTeam")]
[Authorize(AuthenticationSchemes = "backstage")]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult> CreateServiceAsync(string teamName, [FromBody] ServiceConfigRequest serviceFluxConfigRequest)
Expand Down Expand Up @@ -108,6 +112,7 @@ public async Task<ActionResult> CreateServiceAsync(string teamName, [FromBody] S
/// <param name="manifestConfigRequest">The request object containing all the necessary information to update the service in the Flux Config.</param>
/// <returns></returns>
[HttpPatch("{teamName}/services/{service}/environments/{environment}/manifest", Name = "SetEnvironmentManifestForTeamService")]
[Authorize(AuthenticationSchemes = "pipeline")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult> SetEnvironmentManifestAsync(string teamName, string service, string environment, [FromBody] ManifestConfigRequest manifestConfigRequest)
Expand Down Expand Up @@ -137,6 +142,7 @@ public async Task<ActionResult> SetEnvironmentManifestAsync(string teamName, str
/// <param name="environment">Required: Name of the Environment</param>
/// <returns></returns>
[HttpGet("{teamName}/services/{service}/environments/{environment}", Name = "GetEnvironmentForTeamService")]
[Authorize(AuthenticationSchemes = "pipeline")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<ActionResult> GetServiceEnvironmentAsync(string teamName, string service, string environment)
Expand All @@ -160,6 +166,7 @@ public async Task<ActionResult> GetServiceEnvironmentAsync(string teamName, stri
/// <param name="environmentRequest">Required: Details about the Environment for the service</param>
/// <returns></returns>
[HttpPost("{teamName}/services/{service}/environments", Name = "AddEnvironmentForTeamService")]
[Authorize(AuthenticationSchemes = "pipeline")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult> AddServiceEnvironmentAsync(string teamName, string service, [FromBody] string environmentRequest)
Expand Down Expand Up @@ -188,6 +195,7 @@ public async Task<ActionResult> AddServiceEnvironmentAsync(string teamName, stri
/// <param name="serviceName">Optional: Generate manifests only for this service if specified. Default is All services</param>
/// <returns></returns>
[HttpPost("{teamName}/generate", Name = "GenerateFluxConfigForTeam")]
[Authorize(AuthenticationSchemes = "pipeline,backstage")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult> GenerateAsync(string teamName, [FromQuery] string? serviceName, [FromQuery] string? environment = null)
Expand Down
2 changes: 1 addition & 1 deletion src/ADP.Portal.Api/Controllers/GithubTeamsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ namespace ADP.Portal.Api.Controllers;

[Route("api/github/teams")]
[ApiVersion("1.0")]
[Authorize(AuthenticationSchemes = "backstage")]
[ApiController]
public class GithubTeamsController : ControllerBase
{
Expand All @@ -23,6 +22,7 @@ public GithubTeamsController(IGitHubService github, ILogger<GithubTeamsControlle
}

[HttpPut("{teamId?}")]
[Authorize(AuthenticationSchemes = "backstage")]
[ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(GithubTeamDetails))]
[ProducesResponseType(StatusCodes.Status409Conflict)]
public async Task<IActionResult> SyncTeam([FromRoute] int? teamId, [FromBody] SyncTeamRequest request, CancellationToken cancellationToken = default)
Expand Down
22 changes: 15 additions & 7 deletions src/ADP.Portal.Api/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using Azure.Identity;
using Microsoft.Extensions.Options;
using Microsoft.Graph;
using Microsoft.Identity.Web;
using Microsoft.IdentityModel.Logging;
using Microsoft.OpenApi.Models;
using Octokit;
Expand Down Expand Up @@ -61,13 +62,7 @@ public static void ConfigureApp(WebApplicationBuilder builder)
builder.Services.AddLogging();
builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
builder.Services.AddProblemDetails();
builder.Services.AddAuthentication()
.AddJwtBearer("backstage", opt =>
{
builder.Configuration
.GetSection("Authentication:backstage")
.Bind(opt);
});
AddAuthenticationSchemes(builder);
builder.Services.Configure<AdoConfig>(builder.Configuration.GetSection("Ado"));
builder.Services.Configure<AdpAdoProjectConfig>(builder.Configuration.GetSection("AdpAdoProject"));
builder.Services.Configure<AzureAdConfig>(builder.Configuration.GetSection("AzureAd"));
Expand Down Expand Up @@ -157,6 +152,19 @@ public static void ConfigureApp(WebApplicationBuilder builder)
config.ApiVersionReader = new HeaderApiVersionReader("api-version");
});
}

private static void AddAuthenticationSchemes(WebApplicationBuilder builder)
{
var auth = builder.Services.AddAuthentication();
auth.AddJwtBearer(
authenticationScheme: "backstage",
configureOptions: builder.Configuration.GetSection("Authentication:backstage").Bind);
auth.AddMicrosoftIdentityWebApi(
jwtBearerScheme: "pipeline",
configuration: builder.Configuration,
configSectionName: "Authentication:pipeline");
}

private static GitHubClient GetGitHubClient(GitHubAppAuthConfig gitHubAppAuth)
{
var gitHubAppName = gitHubAppAuth.AppName.Replace(" ", "");
Expand Down
7 changes: 6 additions & 1 deletion src/ADP.Portal.Api/appsettings.Development.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,13 @@
"Authority": "http://localhost:7007/api/auth/",
"TokenValidationParameters": {
"ValidateAudience": false,
"ValidateIssuer": false
"ValidateIssuer": false
}
},
"pipeline": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "00000000-0000-0000-0000-000000000000",
"ClientId": "00000000-0000-0000-0000-000000000000"
}
}
}
Loading