|
| 1 | + |
| 2 | +@page "/blog/ai/bedrock/advanced" |
| 3 | +@using TestArena.Blog.Common |
| 4 | +@using TestArena.Blog |
| 5 | +@using System.Linq |
| 6 | +@using TestArena.Blog.Common.NavigationUtils |
| 7 | + |
| 8 | +@code{ |
| 9 | + PageInfo currentPage = SiteMap.Pages.FirstOrDefault(x => x.RelativePath == "/blog/ai/bedrock/advanced")!; |
| 10 | +} |
| 11 | + |
| 12 | +<BlogContainer> |
| 13 | + <Header Title="@currentPage.Header" |
| 14 | + Image="@currentPage.ArticleImage" |
| 15 | + PublishedOn="@currentPage.PublishedOn" |
| 16 | + Authors="Ajay Kumar" |
| 17 | + isOlderThumbnailFormat="@currentPage.IsOlderThumbnailFormat"> |
| 18 | + </Header> |
| 19 | + |
| 20 | + <CalloutBox Type="info" Title="Looking for the basics?"> |
| 21 | + <p>Start with <a href="/blog/ai/bedrock">Getting Started with AWS Bedrock in .NET</a> for the simplest setup and usage.</p> |
| 22 | + </CalloutBox> |
| 23 | + |
| 24 | + <Section Heading="Advanced Authentication & Production Setup" Level="4"> |
| 25 | + <Section Heading="Session Credentials (Local Development)" Level="5"> |
| 26 | + <p>Use this for quick local testing with temporary credentials (e.g., from AWS STS or temporary session tokens).</p> |
| 27 | + <CodeSnippet Language="csharp" Number="2"> |
| 28 | +SessionAWSCredentials GetCredentials() |
| 29 | +{ |
| 30 | + // ⚠️ NEVER hardcode credentials in production! |
| 31 | + string accessKey = "<your-access-key>"; |
| 32 | + string secretKey = "<your-secret-key>"; |
| 33 | + string sessionToken = "<your-session-token>"; |
| 34 | + return new SessionAWSCredentials(accessKey, secretKey, sessionToken); |
| 35 | +} |
| 36 | + </CodeSnippet> |
| 37 | + <CalloutBox Type="warning" Title="Security Warning"> |
| 38 | + <p>Session credentials are temporary and should never be hardcoded. Use them only during development with test accounts.</p> |
| 39 | + </CalloutBox> |
| 40 | + </Section> |
| 41 | + |
| 42 | + <Section Heading="IAM User Credentials (Not Recommended for Production)" Level="5"> |
| 43 | + <p>Use static IAM user credentials for simple scenarios, but this method is less secure for production.</p> |
| 44 | + <CodeSnippet Language="csharp" Number="3"> |
| 45 | +BasicAWSCredentials GetBasicCredentials() |
| 46 | +{ |
| 47 | + string accessKey = Environment.GetEnvironmentVariable("AWS_ACCESS_KEY_ID"); |
| 48 | + string secretKey = Environment.GetEnvironmentVariable("AWS_SECRET_ACCESS_KEY"); |
| 49 | + |
| 50 | + if (string.IsNullOrWhiteSpace(accessKey) || string.IsNullOrWhiteSpace(secretKey)) |
| 51 | + throw new InvalidOperationException("AWS credentials not found in environment variables."); |
| 52 | + |
| 53 | + return new BasicAWSCredentials(accessKey, secretKey); |
| 54 | +} |
| 55 | + </CodeSnippet> |
| 56 | + <CalloutBox Type="tip" Title="Environment Variables"> |
| 57 | + <p>Store credentials in environment variables, not in appsettings files or source code. Use <code>AWS_ACCESS_KEY_ID</code> and <code>AWS_SECRET_ACCESS_KEY</code>.</p> |
| 58 | + </CalloutBox> |
| 59 | + </Section> |
| 60 | + |
| 61 | + <Section Heading="EC2 Instance Profile Role (Production on EC2)" Level="5"> |
| 62 | + <p> |
| 63 | + This is the <b>recommended approach for production applications running on EC2</b>. The SDK automatically retrieves credentials from the instance metadata without any code changes. |
| 64 | + </p> |
| 65 | + <CodeSnippet Language="csharp" Number="4"> |
| 66 | +// No credentials needed! The SDK automatically uses the EC2 instance role. |
| 67 | +var bedrockClient = new AmazonBedrockClient(RegionEndpoint.USEast1); |
| 68 | +var runtimeClient = new AmazonBedrockRuntimeClient(RegionEndpoint.USEast1); |
| 69 | + </CodeSnippet> |
| 70 | + </Section> |
| 71 | + |
| 72 | + <Section Heading="Creating the EC2 Instance Profile Role" Level="5"> |
| 73 | + <p> |
| 74 | + To create an EC2 instance profile role with the minimal permissions needed to list models and invoke them: |
| 75 | + </p> |
| 76 | + <p><b>Step 1: Create an IAM Role</b></p> |
| 77 | + <ol> |
| 78 | + <li>Go to IAM console → Roles → Create Role</li> |
| 79 | + <li>Select "AWS service" → "EC2" as the trusted entity</li> |
| 80 | + <li>Click "Create Role"</li> |
| 81 | + </ol> |
| 82 | + <p><b>Step 2: Add Inline Policy with Required Permissions</b></p> |
| 83 | + <p>Once the role is created, add this inline policy to grant Bedrock permissions:</p> |
| 84 | + <CodeSnippet Language="json" Number="7"> |
| 85 | +{ |
| 86 | + "Version": "2012-10-17", |
| 87 | + "Statement": [ |
| 88 | + { |
| 89 | + "Effect": "Allow", |
| 90 | + "Action": [ |
| 91 | + "bedrock:ListFoundationModels", |
| 92 | + "bedrock:GetFoundationModel" |
| 93 | + ], |
| 94 | + "Resource": "*" |
| 95 | + }, |
| 96 | + { |
| 97 | + "Effect": "Allow", |
| 98 | + "Action": [ |
| 99 | + "bedrock:InvokeModel", |
| 100 | + "bedrock:InvokeModelWithResponseStream" |
| 101 | + ], |
| 102 | + "Resource": "arn:aws:bedrock:*:*:foundation-model/*" |
| 103 | + } |
| 104 | + ] |
| 105 | +} |
| 106 | + </CodeSnippet> |
| 107 | + <p><b>Step 3: Attach the Role to Your EC2 Instance</b></p> |
| 108 | + <ol> |
| 109 | + <li>Go to EC2 console → Instances → Select your instance</li> |
| 110 | + <li>Right-click → Security → Modify IAM role</li> |
| 111 | + <li>Select the role you created</li> |
| 112 | + <li>Click "Update IAM role"</li> |
| 113 | + </ol> |
| 114 | + <p><b>Step 4: Use in Your .NET Code</b></p> |
| 115 | + <p>No code changes needed! The SDK automatically picks up the EC2 instance role:</p> |
| 116 | + <CodeSnippet Language="csharp" Number="8"> |
| 117 | +var bedrockClient = new AmazonBedrockClient(RegionEndpoint.USEast1); |
| 118 | +var runtimeClient = new AmazonBedrockRuntimeClient(RegionEndpoint.USEast1); |
| 119 | + </CodeSnippet> |
| 120 | + </Section> |
| 121 | + |
| 122 | + <Section Heading="Troubleshooting Authentication Issues" Level="5"> |
| 123 | + <p>If you're getting permission errors, check these common issues:</p> |
| 124 | + <ul> |
| 125 | + <li><b>UnauthorizedException or AccessDeniedException:</b> Your credentials don't have Bedrock permissions. Double-check the IAM policy above is attached to your role/user.</li> |
| 126 | + <li><b>InvalidUserID or SignatureDoesNotMatch:</b> Your AWS credentials are incorrect or expired. Re-verify your access key and secret key.</li> |
| 127 | + <li><b>EC2 instance can't access Bedrock:</b> The instance profile role isn't attached, or the IAM policy is missing. Check the instance details in AWS console.</li> |
| 128 | + <li><b>Region issues:</b> Ensure Bedrock is available in your region. Not all AWS regions support Bedrock yet.</li> |
| 129 | + </ul> |
| 130 | + <p><b>Debug tip:</b> Use the AWS CLI to test credentials before using them in your .NET app:</p> |
| 131 | + <CodeSnippet Language="bash" Number="9"> |
| 132 | +aws bedrock list-foundation-models --region us-east-1 |
| 133 | + </CodeSnippet> |
| 134 | + <p style="margin-top: 1em;"><i>Note: The same IAM permissions can also be set up using CloudFormation or AWS CDK if you prefer infrastructure-as-code approaches.</i></p> |
| 135 | + </Section> |
| 136 | + </Section> |
| 137 | + |
| 138 | + <Section Heading="Prompt Engineering & Response Parsing" Level="4"> |
| 139 | + <p>For reliable parsing, craft your prompts to instruct the model to return strict JSON. Here’s a helper for formatting/parsing the response:</p> |
| 140 | + <CodeSnippet Language="csharp"> |
| 141 | +private string FormatJsonString(string input) |
| 142 | +{ |
| 143 | + if (string.IsNullOrWhiteSpace(input)) return input; |
| 144 | + // Try to extract the first JSON array or object from the string |
| 145 | + var match = System.Text.RegularExpressions.Regex.Match(input, |
| 146 | + "(\\{[\\s\\S]*\\}|\\[[\\s\\S]*\\])"); |
| 147 | + if (!match.Success) |
| 148 | + return input; |
| 149 | + var jsonContent = match.Value; |
| 150 | + try |
| 151 | + { |
| 152 | + using var doc = System.Text.Json.JsonDocument.Parse(jsonContent); |
| 153 | + return System.Text.Json.JsonSerializer.Serialize(doc.RootElement, |
| 154 | + new System.Text.Json.JsonSerializerOptions { WriteIndented = true }); |
| 155 | + } |
| 156 | + catch |
| 157 | + { |
| 158 | + // If not valid JSON, return as-is |
| 159 | + return jsonContent; |
| 160 | + } |
| 161 | +} |
| 162 | + </CodeSnippet> |
| 163 | + <CalloutBox Type="tip" Title="Prompt Engineering"> |
| 164 | + <p>Always instruct the model to return a strict JSON array/object and nothing else for easier parsing.</p> |
| 165 | + </CalloutBox> |
| 166 | + </Section> |
| 167 | + |
| 168 | + <Section Heading="Summary & Best Practices" Level="4"> |
| 169 | + <ul> |
| 170 | + <li><b>Advanced authentication</b> enables secure, scalable, and production-ready AWS Bedrock integration in .NET.</li> |
| 171 | + <li><b>Use EC2 instance roles</b> for production workloads—never hardcode credentials.</li> |
| 172 | + <li><b>Prompt engineering</b> and response parsing are key for reliable GenAI workflows.</li> |
| 173 | + <li>Refer to AWS documentation for the latest best practices and SDK updates.</li> |
| 174 | + </ul> |
| 175 | + <p> |
| 176 | + For most users, the shared credentials file is sufficient. Move to advanced setups only when your deployment or security needs require it. |
| 177 | + </p> |
| 178 | + </Section> |
| 179 | + |
| 180 | + <EndNotes RepositoryLink="https://github.com/ajaysskumar/ai-playground" /> |
| 181 | +</BlogContainer> |
0 commit comments