mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 08:23:12 +00:00
Merge pull request #4 from Sea-Haven-Industries/fix/remove-hardcoded-secrets
fix(security): remove hardcoded secrets from source
This commit is contained in:
commit
047ad23c81
11 changed files with 118 additions and 40 deletions
34
.env.example
Normal file
34
.env.example
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# Sea Haven Industries — shoc-backend required configuration
|
||||
#
|
||||
# This file documents the secrets that used to be hardcoded in appsettings*.json
|
||||
# and source files. Copy the values into one of the supported configuration sources;
|
||||
# do NOT commit real values.
|
||||
#
|
||||
# .NET resolves configuration in this order (later wins):
|
||||
# 1. appsettings.json / appsettings.{Environment}.json (committed — placeholders only)
|
||||
# 2. User Secrets (local dev): dotnet user-secrets set "Key:Sub" "value"
|
||||
# 3. Environment variables (use "__" as the section separator)
|
||||
#
|
||||
# Environment-variable form is shown below. In AWS Elastic Beanstalk these map to
|
||||
# environment properties; locally you can export them or use dotnet user-secrets.
|
||||
#
|
||||
# AWS credentials for the S3 client are NOT listed here on purpose: UploadFileHp now
|
||||
# uses the AWS SDK default credential chain (env AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY,
|
||||
# the shared profile/SSO, or the EC2/ECS instance role). Prefer an instance role in prod.
|
||||
|
||||
# --- SQL Server connection string (Api.SeaHavenIndustries + SeaHavenIndustries) ---
|
||||
ConnectionStrings__DefaultConnection=Server=<host>;Initial Catalog=<db>;User Id=<user>;Password=<password>;MultipleActiveResultSets=true
|
||||
|
||||
# --- SendGrid (transactional email) ---
|
||||
SendGrid__ApiKey=SG.xxxxxxxxxxxxxxxxxxxxxx
|
||||
|
||||
# --- JWT signing secret (Api.SeaHavenIndustries) ---
|
||||
JWT__Secret=<a-long-random-secret>
|
||||
|
||||
# --- Google Maps / Places API key (SeaHavenIndustries Blazor app) ---
|
||||
GoogleMaps__ApiKey=AIzaSyXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
|
||||
# --- AWS S3 (optional; prefer instance role / SSO over static keys) ---
|
||||
# AWS_ACCESS_KEY_ID=
|
||||
# AWS_SECRET_ACCESS_KEY=
|
||||
# AWS_REGION=us-east-2
|
||||
|
|
@ -27,19 +27,19 @@ namespace Api.SeaHavenIndustries.Helper
|
|||
//mail.Body = body;
|
||||
//mail.IsBodyHtml = true;
|
||||
//SmtpClient smtp = new SmtpClient("mail.codevoir.com");
|
||||
//NetworkCredential Credentials = new NetworkCredential("infoesquall@codevoir.com", "Abc123!@#");
|
||||
//NetworkCredential Credentials = new NetworkCredential("<smtp-user>", "<smtp-password>");
|
||||
//smtp.UseDefaultCredentials = false;
|
||||
//smtp.Credentials = Credentials;
|
||||
//smtp.Port = 8889; //25 alternative port number is 8889
|
||||
//smtp.EnableSsl = false;
|
||||
|
||||
//smtp.Send(mail);
|
||||
//var apiKey = Environment.GetEnvironmentVariable("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\r\n");
|
||||
//var apiKey1 = Environment.GetEnvironmentVariable("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");
|
||||
//var apiKey = Environment.GetEnvironmentVariable("<SENDGRID_API_KEY>\r\n");
|
||||
//var apiKey1 = Environment.GetEnvironmentVariable("<SENDGRID_API_KEY>");
|
||||
// var apiKey2 = Environment.GetEnvironmentVariable("SENDGRID_API_KEY");
|
||||
var apiKey = _configuration.GetValue<string>("SendGrid:ApiKey");
|
||||
|
||||
//var apiKey = "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";
|
||||
//var apiKey = "<SENDGRID_API_KEY>";
|
||||
var client = new SendGridClient(apiKey);
|
||||
var from = new EmailAddress("tech@seahavenind.com", "Sea haven Industries");
|
||||
//var subject = "Sending with SendGrid is Fun";
|
||||
|
|
@ -65,7 +65,7 @@ namespace Api.SeaHavenIndustries.Helper
|
|||
|
||||
var apiKey = _configuration.GetValue<string>("SendGrid:ApiKey");
|
||||
|
||||
//var apiKey = "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";
|
||||
//var apiKey = "<SENDGRID_API_KEY>";
|
||||
var client = new SendGridClient(apiKey);
|
||||
var from = new EmailAddress("tech@seahavenind.com", "Sea haven Industries");
|
||||
//var subject = "Sending with SendGrid is Fun";
|
||||
|
|
|
|||
|
|
@ -2,11 +2,10 @@
|
|||
"ConnectionStrings": {
|
||||
//"DefaultConnection": "Server=DESKTOP-64LC14O\SQLEXPRESS;Database=SeahavenIndustries;TrustServerCertificate=True;Trusted_Connection=True;MultipleActiveResultSets=true",
|
||||
|
||||
// Test database
|
||||
//"DefaultConnection": "Server=SQL5112.site4now.net;Initial Catalog=db_a7141e_seahavenindustries;User Id=db_a7141e_seahavenindustries_admin;Password=Abc123!@#;MultipleActiveResultSets=true"
|
||||
|
||||
//Client Database
|
||||
"DefaultConnection": "Server=SQL5112.site4now.net;Initial Catalog=db_a7141e_seahavenindustry;User Id=db_a7141e_seahavenindustry_admin;Password=Abc123!@#;MultipleActiveResultSets=true"
|
||||
// Provide the real value via environment variable ConnectionStrings__DefaultConnection or user-secrets.
|
||||
// Do NOT commit credentials. This file is committed, so keep only the placeholder here.
|
||||
"DefaultConnection": "${CONNECTION_STRING}"
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
|
|
@ -15,12 +14,14 @@
|
|||
}
|
||||
},
|
||||
"SendGrid": {
|
||||
"ApiKey": "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"
|
||||
// Provide the real value via environment variable SendGrid__ApiKey or user-secrets.
|
||||
"ApiKey": "${SENDGRID_API_KEY}"
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"JWT": {
|
||||
"ValidAudience": "http://localhost:4200",
|
||||
"ValidIssuer": "http://localhost:7195",
|
||||
"Secret": "JWTAuthenticationHIGHsecuredPasswordVVVp1OH7Xzyr"
|
||||
// Provide the real value via environment variable JWT__Secret or user-secrets.
|
||||
"Secret": "${JWT_SECRET}"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
{
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Server=SQL5112.site4now.net;Initial Catalog=db_a7141e_seahavenindustry;User Id=db_a7141e_seahavenindustry_admin;Password=Abc123!@#;MultipleActiveResultSets=true"
|
||||
// Provide the real value via environment variable ConnectionStrings__DefaultConnection
|
||||
// (e.g. Elastic Beanstalk environment property) or the instance secret store. Do NOT commit credentials.
|
||||
"DefaultConnection": "${CONNECTION_STRING}"
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
|
|
@ -9,12 +11,14 @@
|
|||
}
|
||||
},
|
||||
"SendGrid": {
|
||||
"ApiKey": "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"
|
||||
// Provide the real value via environment variable SendGrid__ApiKey or the instance secret store.
|
||||
"ApiKey": "${SENDGRID_API_KEY}"
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"JWT": {
|
||||
"ValidAudience": "http://console.seahavenind.com",
|
||||
"ValidIssuer": "http://console.seahavenind.com",
|
||||
"Secret": "JWTAuthenticationHIGHsecuredPasswordVVVp1OH7Xzyr"
|
||||
// Provide the real value via environment variable JWT__Secret or the instance secret store.
|
||||
"Secret": "${JWT_SECRET}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,11 +2,10 @@
|
|||
"ConnectionStrings": {
|
||||
//"DefaultConnection": "Server=DESKTOP-64LC14O\SQLEXPRESS;Database=SeahavenIndustries;TrustServerCertificate=True;Trusted_Connection=True;MultipleActiveResultSets=true",
|
||||
|
||||
// Test database
|
||||
//"DefaultConnection": "Server=SQL5112.site4now.net;Initial Catalog=db_a7141e_seahavenindustries;User Id=db_a7141e_seahavenindustries_admin;Password=Abc123!@#;MultipleActiveResultSets=true"
|
||||
|
||||
//Client Database
|
||||
"DefaultConnection": "Server=SQL5112.site4now.net;Initial Catalog=db_a7141e_seahavenindustry;User Id=db_a7141e_seahavenindustry_admin;Password=Abc123!@#;MultipleActiveResultSets=true"
|
||||
// Provide the real value via environment variable ConnectionStrings__DefaultConnection,
|
||||
// user-secrets, or appsettings.Development.json (which is gitignored). Do NOT commit credentials.
|
||||
"DefaultConnection": "${CONNECTION_STRING}"
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
|
|
@ -15,12 +14,14 @@
|
|||
}
|
||||
},
|
||||
"SendGrid": {
|
||||
"ApiKey": "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"
|
||||
// Provide the real value via environment variable SendGrid__ApiKey or user-secrets.
|
||||
"ApiKey": "${SENDGRID_API_KEY}"
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"JWT": {
|
||||
"ValidAudience": "http://localhost:4200",
|
||||
"ValidIssuer": "http://localhost:7195",
|
||||
"Secret": "JWTAuthenticationHIGHsecuredPasswordVVVp1OH7Xzyr"
|
||||
// Provide the real value via environment variable JWT__Secret or user-secrets.
|
||||
"Secret": "${JWT_SECRET}"
|
||||
}
|
||||
}
|
||||
|
|
@ -529,3 +529,36 @@ See these files for complete examples:
|
|||
- **Asset**: `AssetController.cs`, `AssetService.cs`, `AssetDataService.cs`
|
||||
|
||||
All follow the same Clean Architecture pattern!
|
||||
|
||||
---
|
||||
|
||||
## 🔐 Configuration & Secrets
|
||||
|
||||
No secrets are stored in source. The committed `appsettings*.json` files hold only
|
||||
`${PLACEHOLDER}` tokens; real values must be supplied at runtime through one of the
|
||||
standard .NET configuration sources (later sources win):
|
||||
|
||||
1. `appsettings.json` / `appsettings.{Environment}.json` — committed, placeholders only.
|
||||
2. **User Secrets** (local dev): `dotnet user-secrets set "Section:Key" "value"`.
|
||||
3. **Environment variables** — use `__` (double underscore) as the section separator.
|
||||
In AWS Elastic Beanstalk these are the environment properties.
|
||||
|
||||
See `.env.example` in the repo root for the full list. Required values:
|
||||
|
||||
| Setting | Env-var form | Used by | Notes |
|
||||
|---|---|---|---|
|
||||
| `ConnectionStrings:DefaultConnection` | `ConnectionStrings__DefaultConnection` | Both projects | SQL Server connection string |
|
||||
| `SendGrid:ApiKey` | `SendGrid__ApiKey` | Both projects | Transactional email |
|
||||
| `JWT:Secret` | `JWT__Secret` | `Api.SeaHavenIndustries` | JWT signing key |
|
||||
| `GoogleMaps:ApiKey` | `GoogleMaps__ApiKey` | `SeaHavenIndustries` (Blazor) | Maps/Places; read in `App.razor` + `Home.razor` |
|
||||
|
||||
### AWS credentials
|
||||
|
||||
`UploadFileHp` (S3 uploads) uses the **AWS SDK default credential chain** — it no longer
|
||||
hardcodes access keys. Credentials resolve from `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`
|
||||
env vars, the shared profile/SSO, or (preferred in production) the EC2/ECS instance role.
|
||||
The region comes from `AddDefaultAWSOptions` in `Program.cs`.
|
||||
|
||||
> ⚠️ The secrets previously committed to this repo (DB password, SendGrid key, JWT secret,
|
||||
> Google Maps keys, AWS access key) should be considered compromised and **rotated**.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
@inject IConfiguration Configuration
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
|
|
@ -17,7 +18,7 @@
|
|||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css" integrity="sha512-Kc323vGBEqzTmouAECnVceyQqyqdsSiqLQISBL29aUW4U/M7pSPA/gEUZQqv1cwx4OnYxTxve5UMg5GT6L4JJg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||
<!-- Material Icons -->
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons+Round" rel="stylesheet">
|
||||
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDK_mNMt1b3zwmykVLauDUjnoz8DhuLI70&v=3&libraries=places"></script>
|
||||
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=@Configuration["GoogleMaps:ApiKey"]&v=3&libraries=places"></script>
|
||||
|
||||
<link rel="stylesheet" href="_content/Radzen.Blazor/css/default-base.css">
|
||||
<!-- JS File -->
|
||||
|
|
|
|||
|
|
@ -298,7 +298,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="col-12 px-5 mb-4">
|
||||
<RadzenGoogleMap ApiKey="AIzaSyBYwcFy_LS_UpdCIv7KZJUVhj9kMyPFdmk" @ref=map style="height: 400px" Options=@(new Dictionary<string, object> { { "disableDoubleClickZoom", true } })
|
||||
<RadzenGoogleMap ApiKey="@Configuration["GoogleMaps:ApiKey"]" @ref=map style="height: 400px" Options=@(new Dictionary<string, object> { { "disableDoubleClickZoom", true } })
|
||||
Zoom=@zoom Center=@(new GoogleMapPosition() { Lat = 42.6977, Lng = 23.3219 }) MapClick=@OnMapClick>
|
||||
<Markers>
|
||||
@foreach (var itm in setmappins)
|
||||
|
|
@ -341,6 +341,7 @@
|
|||
@inject IAccountRepository _aservice;
|
||||
@inject ISettingsRepository _Seservice;
|
||||
@inject HttpClient Http
|
||||
@inject IConfiguration Configuration
|
||||
|
||||
@code {
|
||||
private IEnumerable<ApplicationUser>? users { get; set; }
|
||||
|
|
@ -508,7 +509,7 @@
|
|||
}
|
||||
private async Task<(double Latitude, double Longitude)> GetLatLng(string placeId)
|
||||
{
|
||||
const string apiKey = "AIzaSyBYwcFy_LS_UpdCIv7KZJUVhj9kMyPFdmk"; // Replace with your API key
|
||||
var apiKey = Configuration["GoogleMaps:ApiKey"]; // Injected from configuration (env var GoogleMaps__ApiKey / user-secrets)
|
||||
//var apiUrl = $"https://places.googleapis.com/v1/places/{placeId}";
|
||||
var apiUrl = $"https://maps.googleapis.com/maps/api/place/autocomplete/json?input=Vict&language=pt_BR&types=%28cities%29&key={apiKey}";
|
||||
// var apiUrl = $"https://places.googleapis.com/v1/places/{placeId}?fields=id,displayName&key={apiKey}";
|
||||
|
|
|
|||
|
|
@ -31,19 +31,19 @@ namespace SeaHavenIndustries.Helper
|
|||
//mail.Body = body;
|
||||
//mail.IsBodyHtml = true;
|
||||
//SmtpClient smtp = new SmtpClient("mail.codevoir.com");
|
||||
//NetworkCredential Credentials = new NetworkCredential("infoesquall@codevoir.com", "Abc123!@#");
|
||||
//NetworkCredential Credentials = new NetworkCredential("<smtp-user>", "<smtp-password>");
|
||||
//smtp.UseDefaultCredentials = false;
|
||||
//smtp.Credentials = Credentials;
|
||||
//smtp.Port = 8889; //25 alternative port number is 8889
|
||||
//smtp.EnableSsl = false;
|
||||
|
||||
//smtp.Send(mail);
|
||||
//var apiKey = Environment.GetEnvironmentVariable("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\r\n");
|
||||
//var apiKey1 = Environment.GetEnvironmentVariable("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");
|
||||
//var apiKey = Environment.GetEnvironmentVariable("<SENDGRID_API_KEY>\r\n");
|
||||
//var apiKey1 = Environment.GetEnvironmentVariable("<SENDGRID_API_KEY>");
|
||||
// var apiKey2 = Environment.GetEnvironmentVariable("SENDGRID_API_KEY");
|
||||
var apiKey = _configuration.GetValue<string>("SendGrid:ApiKey");
|
||||
|
||||
//var apiKey = "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";
|
||||
//var apiKey = "<SENDGRID_API_KEY>";
|
||||
var client = new SendGridClient(apiKey);
|
||||
var from = new EmailAddress("tech@seahavenind.com", "Sea haven Industries");
|
||||
//var subject = "Sending with SendGrid is Fun";
|
||||
|
|
@ -69,7 +69,7 @@ namespace SeaHavenIndustries.Helper
|
|||
|
||||
var apiKey = _configuration.GetValue<string>("SendGrid:ApiKey");
|
||||
|
||||
//var apiKey = "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";
|
||||
//var apiKey = "<SENDGRID_API_KEY>";
|
||||
var client = new SendGridClient(apiKey);
|
||||
var from = new EmailAddress("tech@seahavenind.com", "Sea haven Industries");
|
||||
//var subject = "Sending with SendGrid is Fun";
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ using Microsoft.AspNetCore.Components.Forms;
|
|||
using SeaHavenIndustries.ViewModel;
|
||||
using Amazon.S3;
|
||||
using Amazon.S3.Model;
|
||||
using Amazon.Runtime;
|
||||
|
||||
namespace SeaHavenIndustries.Helper
|
||||
{
|
||||
|
|
@ -16,13 +15,13 @@ namespace SeaHavenIndustries.Helper
|
|||
|
||||
public UploadFileHp(IWebHostEnvironment hosting, IHttpContextAccessor httpContextAccessor, IAmazonS3 s3Client)
|
||||
{
|
||||
|
||||
_hosting = hosting;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
var awsCredentials = new BasicAWSCredentials("AKIAUY6EP2OAGEFSEP4W", "7xF+1RoO0pqyAWu/Lt9zP3z5HvHS/UjcCx2KbDbc");
|
||||
|
||||
_s3Client = new AmazonS3Client(awsCredentials, Amazon.RegionEndpoint.USEast2);
|
||||
|
||||
// Use the IAmazonS3 client supplied by DI (registered via AddAWSService<IAmazonS3>()).
|
||||
// It resolves credentials through the AWS SDK default credential chain
|
||||
// (environment variables, shared profile/SSO, or the EC2/ECS instance role) and the
|
||||
// region from AddDefaultAWSOptions in Program.cs. Do NOT hardcode access keys here.
|
||||
_s3Client = s3Client;
|
||||
}
|
||||
|
||||
//public async Task<UploadResponseVm> UploadFiles(IBrowserFile file, string? path)
|
||||
|
|
|
|||
|
|
@ -2,11 +2,10 @@
|
|||
"ConnectionStrings": {
|
||||
//"DefaultConnection": "Server=.;Database=SeahavenIndustries;TrustServerCertificate=True;Trusted_Connection=True;MultipleActiveResultSets=true",
|
||||
//"DefaultConnection": "Server=.\\SqlExpress;Database=SeahavenIndustries;TrustServerCertificate=True;Trusted_Connection=True;MultipleActiveResultSets=true",
|
||||
// Test database
|
||||
//"DefaultConnection": "Server=SQL5112.site4now.net;Initial Catalog=db_a7141e_seahavenindustries;User Id=db_a7141e_seahavenindustries_admin;Password=Abc123!@#;MultipleActiveResultSets=true",
|
||||
|
||||
//Client Database
|
||||
"DefaultConnection": "Server=SQL5112.site4now.net;Initial Catalog=db_a7141e_seahavenindustry;User Id=db_a7141e_seahavenindustry_admin;Password=Abc123!@#;MultipleActiveResultSets=true",
|
||||
// Provide the real value via environment variable ConnectionStrings__DefaultConnection,
|
||||
// user-secrets, or appsettings.Development.json (which is gitignored). Do NOT commit credentials.
|
||||
"DefaultConnection": "${CONNECTION_STRING}",
|
||||
"excelconnection": "Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties='Excel 8.0;HDR=YES'"
|
||||
},
|
||||
"Logging": {
|
||||
|
|
@ -16,7 +15,12 @@
|
|||
}
|
||||
},
|
||||
"SendGrid": {
|
||||
"ApiKey": "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"
|
||||
// Provide the real value via environment variable SendGrid__ApiKey or user-secrets.
|
||||
"ApiKey": "${SENDGRID_API_KEY}"
|
||||
},
|
||||
"GoogleMaps": {
|
||||
// Provide the real value via environment variable GoogleMaps__ApiKey or user-secrets.
|
||||
"ApiKey": "${GOOGLE_MAPS_API_KEY}"
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue