Skip to content

Commit 395fecc

Browse files
committed
feat: Update Azure Storage documentation and SDK usage examples
- Enhanced Azure Storage documentation with detailed SDK package information for multiple languages. - Added quick start examples for JavaScript, Python, C#, Java, Go, and Rust using DefaultAzureCredential. - Introduced a new SDK usage guide with installation commands and quick start examples for Azure Storage services. - Updated Azure Validate skill documentation to reference global rules correctly. - Created global rules documentation for mandatory checks across all skills. - Added GitHub Copilot skill documentation, including setup, deployment, and critical rules. - Introduced a test harness for verifying Copilot SDK and Extensions functionality post-deployment. - Updated the web application to reflect the increase in Azure skills from 28 to 29.
1 parent 99ef131 commit 395fecc

File tree

21 files changed

+1168
-43
lines changed

21 files changed

+1168
-43
lines changed

cli/counts.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
22
"agents": 16,
3-
"skills": 28
3+
"skills": 29
44
}

cli/extension.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ displayName: Azure Copilot
66
description: |
77
AI-powered Azure development assistant. Describe what you want to build,
88
and Copilot builds and deploys it to Azure. Includes 16 specialized agents
9-
and 28 Azure skills.
9+
and 29 Azure skills.
1010
usage: azd copilot <command> [options]
1111
version: 0.1.0
1212
entryPoint: copilot

cli/src/internal/assets/ghcp4a-skills/azure-deploy/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Activate this skill when user wants to:
2424
1. Run after azure-prepare and azure-validate
2525
2. Manifest must exist with status `Validated`
2626
3. **Pre-deploy checklist required**[pre-deploy-checklist](references/pre-deploy-checklist.md)
27-
4.**Destructive actions require `ask_user`**[global-rules](../_shared/global-rules.md)
27+
4.**Destructive actions require `ask_user`**[global-rules](references/global-rules.md)
2828

2929
---
3030

cli/src/internal/assets/ghcp4a-skills/_shared/global-rules.md renamed to cli/src/internal/assets/ghcp4a-skills/azure-deploy/references/global-rules.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,4 @@ ask_user(
3939
- Azure subscription (show actual name and ID)
4040
- Azure region/location
4141

42-
See [pre-deploy-checklist](../azure-deploy/references/pre-deploy-checklist.md).
42+
See [pre-deploy-checklist](pre-deploy-checklist.md).

cli/src/internal/assets/ghcp4a-skills/azure-prepare/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Activate this skill when user wants to:
3131
4. Follow linked references for best practices and guidance
3232
5. Update `.azure/preparation-manifest.md` after each phase
3333
6. Invoke **azure-validate** before any deployment
34-
7.**Destructive actions require `ask_user`**[global-rules](../_shared/global-rules.md)
34+
7.**Destructive actions require `ask_user`**[global-rules](references/global-rules.md)
3535

3636
> **⛔ MANDATORY USER CONFIRMATION REQUIRED**
3737
>
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Global Rules
2+
3+
> **MANDATORY** — These rules apply to ALL skills. Violations are unacceptable.
4+
5+
## Rule 1: Destructive Actions Require User Confirmation
6+
7+
**ALWAYS use `ask_user`** before ANY destructive action.
8+
9+
### What is Destructive?
10+
11+
| Category | Examples |
12+
|----------|----------|
13+
| **Delete** | `az group delete`, `azd down`, `rm -rf`, delete resource |
14+
| **Overwrite** | Replace existing files, overwrite config, reset settings |
15+
| **Irreversible** | Purge Key Vault, delete storage account, drop database |
16+
| **Cost Impact** | Provision expensive resources, scale up significantly |
17+
| **Security** | Expose secrets, change access policies, modify RBAC |
18+
19+
### How to Confirm
20+
21+
```
22+
ask_user(
23+
question: "This will permanently delete resource group 'rg-myapp'. Continue?",
24+
choices: ["Yes, delete it", "No, cancel"]
25+
)
26+
```
27+
28+
### No Exceptions
29+
30+
- Do NOT assume user wants to delete/overwrite
31+
- Do NOT proceed based on "the user asked to deploy" (deploy ≠ delete old)
32+
- Do NOT batch destructive actions without individual confirmation
33+
34+
---
35+
36+
## Rule 2: Never Assume Subscription or Location
37+
38+
**ALWAYS use `ask_user`** to confirm:
39+
- Azure subscription (show actual name and ID)
40+
- Azure region/location

cli/src/internal/assets/ghcp4a-skills/azure-prepare/references/security.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,25 @@ Use Microsoft Defender for Cloud for:
221221

222222
---
223223

224+
## Azure Identity SDK
225+
226+
All Azure SDKs use their language's Identity library for credential-free authentication via `DefaultAzureCredential` or managed identity. Rust uses `DeveloperToolsCredential` as it doesn't have a `DefaultAzureCredential` equivalent.
227+
228+
| Language | Package | Install |
229+
|----------|---------|---------|
230+
| .NET | `Azure.Identity` | `dotnet add package Azure.Identity` |
231+
| Java | `azure-identity` | Maven: `com.azure:azure-identity` |
232+
| JavaScript | `@azure/identity` | `npm install @azure/identity` |
233+
| Python | `azure-identity` | `pip install azure-identity` |
234+
| Go | `azidentity` | `go get github.com/Azure/azure-sdk-for-go/sdk/azidentity` |
235+
| Rust | `azure_identity` | `cargo add azure_identity` |
236+
237+
For Key Vault SDK examples, see: [key-vault.md](services/key-vault.md)
238+
239+
For Storage SDK examples, see: [storage.md](services/storage.md)
240+
241+
---
242+
224243
## Further Reading
225244

226245
- [Key Vault documentation](https://learn.microsoft.com/azure/key-vault/general/overview)

cli/src/internal/assets/ghcp4a-skills/azure-prepare/references/services/key-vault.md

Lines changed: 76 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -117,48 +117,102 @@ secrets: [
117117
]
118118
```
119119

120-
## SDK Access
120+
## Connection Patterns
121121

122-
### Node.js
122+
### SDK Packages
123123

124-
```javascript
125-
const { SecretClient } = require("@azure/keyvault-secrets");
126-
const { DefaultAzureCredential } = require("@azure/identity");
124+
| Language | Secrets | Keys | Certificates |
125+
|----------|---------|------|--------------|
126+
| .NET | `Azure.Security.KeyVault.Secrets` | `Azure.Security.KeyVault.Keys` | `Azure.Security.KeyVault.Certificates` |
127+
| Java | `azure-security-keyvault-secrets` | `azure-security-keyvault-keys` | `azure-security-keyvault-certificates` |
128+
| JavaScript | `@azure/keyvault-secrets` | `@azure/keyvault-keys` | `@azure/keyvault-certificates` |
129+
| Python | `azure-keyvault-secrets` | `azure-keyvault-keys` | `azure-keyvault-certificates` |
130+
| Go | `azsecrets` | `azkeys` | `azcertificates` |
131+
| Rust | `azure_security_keyvault_secrets` | `azure_security_keyvault_keys` | `azure_security_keyvault_certificates` |
132+
133+
### JavaScript
127134

128-
const client = new SecretClient(
129-
process.env.KEY_VAULT_URL,
130-
new DefaultAzureCredential()
131-
);
135+
```javascript
136+
import { DefaultAzureCredential } from "@azure/identity";
137+
import { SecretClient } from "@azure/keyvault-secrets";
132138

139+
const client = new SecretClient(process.env.KEY_VAULT_URL, new DefaultAzureCredential());
133140
const secret = await client.getSecret("database-connection-string");
134-
console.log(secret.value);
141+
// Use secret.value securely - do not log secrets
135142
```
136143

137144
### Python
138145

139146
```python
147+
import os
140148
from azure.keyvault.secrets import SecretClient
141149
from azure.identity import DefaultAzureCredential
142150

143-
client = SecretClient(
144-
vault_url=os.environ["KEY_VAULT_URL"],
145-
credential=DefaultAzureCredential()
146-
)
147-
151+
client = SecretClient(vault_url=os.environ["KEY_VAULT_URL"], credential=DefaultAzureCredential())
148152
secret = client.get_secret("database-connection-string")
149-
print(secret.value)
153+
# Use secret.value securely - do not log secrets
150154
```
151155

152-
### .NET
156+
### C#
153157

154158
```csharp
155-
var client = new SecretClient(
156-
new Uri(Environment.GetEnvironmentVariable("KEY_VAULT_URL")),
157-
new DefaultAzureCredential()
158-
);
159+
using Azure.Identity;
160+
using Azure.Security.KeyVault.Secrets;
159161

162+
var client = new SecretClient(new Uri(Environment.GetEnvironmentVariable("KEY_VAULT_URL")), new DefaultAzureCredential());
160163
KeyVaultSecret secret = await client.GetSecretAsync("database-connection-string");
161-
Console.WriteLine(secret.Value);
164+
// Use secret.Value securely - do not log secrets
165+
```
166+
167+
### Java
168+
169+
```java
170+
import com.azure.identity.*;
171+
import com.azure.security.keyvault.secrets.*;
172+
import com.azure.security.keyvault.secrets.models.*;
173+
174+
SecretClient client = new SecretClientBuilder()
175+
.vaultUrl(System.getenv("KEY_VAULT_URL"))
176+
.credential(new DefaultAzureCredentialBuilder().build())
177+
.buildClient();
178+
KeyVaultSecret secret = client.getSecret("database-connection-string");
179+
// Use secret.getValue() securely - do not log secrets
180+
```
181+
182+
### Go
183+
184+
```go
185+
package main
186+
187+
import (
188+
"context"
189+
"os"
190+
191+
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
192+
"github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets"
193+
)
194+
195+
func main() {
196+
cred, _ := azidentity.NewDefaultAzureCredential(nil)
197+
client, _ := azsecrets.NewClient(os.Getenv("KEY_VAULT_URL"), cred, nil)
198+
199+
resp, _ := client.GetSecret(context.Background(), "database-connection-string", "", nil)
200+
// Use *resp.Value securely - do not log secrets
201+
}
202+
```
203+
204+
### Rust
205+
206+
Note: Rust uses `DeveloperToolsCredential` as it doesn't have a `DefaultAzureCredential` equivalent.
207+
208+
```rust
209+
use azure_identity::DeveloperToolsCredential;
210+
use azure_security_keyvault_secrets::SecretClient;
211+
212+
let credential = DeveloperToolsCredential::new(None)?;
213+
let client = SecretClient::new(std::env::var("KEY_VAULT_URL")?, credential.clone(), None)?;
214+
let secret = client.get_secret("database-connection-string", None).await?.into_model()?;
215+
// Use secret.value securely - do not log secrets
162216
```
163217

164218
## Environment Variables

cli/src/internal/assets/ghcp4a-skills/azure-prepare/references/services/storage.md

Lines changed: 99 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -137,35 +137,122 @@ resource fileShare 'Microsoft.Storage/storageAccounts/fileServices/shares@2023-0
137137

138138
## Connection Patterns
139139

140-
### Node.js
140+
### SDK Packages
141+
142+
| Language | Blob | Queue | File Share | Data Lake |
143+
|----------|------|-------|------------|-----------|
144+
| .NET | `Azure.Storage.Blobs` | `Azure.Storage.Queues` | `Azure.Storage.Files.Shares` | `Azure.Storage.Files.DataLake` |
145+
| Java | `azure-storage-blob` | `azure-storage-queue` | `azure-storage-file-share` | `azure-storage-file-datalake` |
146+
| JavaScript | `@azure/storage-blob` | `@azure/storage-queue` | `@azure/storage-file-share` | `@azure/storage-file-datalake` |
147+
| Python | `azure-storage-blob` | `azure-storage-queue` | `azure-storage-file-share` | `azure-storage-file-datalake` |
148+
| Go | `azblob` | `azqueue` | `azfile` | `azdatalake` |
149+
| Rust | `azure_storage_blob` | `azure_storage_queue` | - | - |
150+
151+
### JavaScript
141152

142153
```javascript
143-
const { BlobServiceClient } = require("@azure/storage-blob");
154+
import { DefaultAzureCredential } from "@azure/identity";
155+
import { BlobServiceClient } from "@azure/storage-blob";
144156

145-
const blobServiceClient = BlobServiceClient.fromConnectionString(
146-
process.env.AZURE_STORAGE_CONNECTION_STRING
157+
const client = new BlobServiceClient(
158+
`https://${process.env.AZURE_STORAGE_ACCOUNT}.blob.core.windows.net`,
159+
new DefaultAzureCredential()
147160
);
148-
const containerClient = blobServiceClient.getContainerClient("uploads");
161+
const container = client.getContainerClient("uploads");
162+
const blob = container.getBlockBlobClient("my-file.txt");
163+
await blob.uploadData(Buffer.from("Hello, Azure Storage!"));
149164
```
150165

151166
### Python
152167

153168
```python
169+
import os
170+
from azure.identity import DefaultAzureCredential
154171
from azure.storage.blob import BlobServiceClient
155172

156-
blob_service_client = BlobServiceClient.from_connection_string(
157-
os.environ["AZURE_STORAGE_CONNECTION_STRING"]
173+
service = BlobServiceClient(
174+
account_url=f"https://{os.environ['AZURE_STORAGE_ACCOUNT']}.blob.core.windows.net",
175+
credential=DefaultAzureCredential()
158176
)
159-
container_client = blob_service_client.get_container_client("uploads")
177+
container = service.get_container_client("uploads")
178+
blob = container.get_blob_client("my-file.txt")
179+
blob.upload_blob(b"Hello, Azure Storage!", overwrite=True)
160180
```
161181

162-
### .NET
182+
### C#
163183

164184
```csharp
165-
var blobServiceClient = new BlobServiceClient(
166-
Environment.GetEnvironmentVariable("AZURE_STORAGE_CONNECTION_STRING")
185+
using Azure.Identity;
186+
using Azure.Storage.Blobs;
187+
188+
var accountName = Environment.GetEnvironmentVariable("AZURE_STORAGE_ACCOUNT");
189+
var client = new BlobServiceClient(
190+
new Uri($"https://{accountName}.blob.core.windows.net"),
191+
new DefaultAzureCredential()
167192
);
168-
var containerClient = blobServiceClient.GetBlobContainerClient("uploads");
193+
var container = client.GetBlobContainerClient("uploads");
194+
var blob = container.GetBlobClient("my-file.txt");
195+
await blob.UploadAsync(BinaryData.FromString("Hello, Azure Storage!"), overwrite: true);
196+
```
197+
198+
### Java
199+
200+
```java
201+
import com.azure.identity.*;
202+
import com.azure.storage.blob.*;
203+
import com.azure.core.util.BinaryData;
204+
205+
BlobServiceClient client = new BlobServiceClientBuilder()
206+
.endpoint("https://" + System.getenv("AZURE_STORAGE_ACCOUNT") + ".blob.core.windows.net")
207+
.credential(new DefaultAzureCredentialBuilder().build())
208+
.buildClient();
209+
BlobContainerClient container = client.getBlobContainerClient("uploads");
210+
BlobClient blob = container.getBlobClient("my-file.txt");
211+
blob.upload(BinaryData.fromString("Hello, Azure Storage!"), true);
212+
```
213+
214+
### Go
215+
216+
```go
217+
package main
218+
219+
import (
220+
"context"
221+
"os"
222+
223+
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
224+
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
225+
)
226+
227+
func main() {
228+
cred, _ := azidentity.NewDefaultAzureCredential(nil)
229+
client, _ := azblob.NewClient(
230+
"https://"+os.Getenv("AZURE_STORAGE_ACCOUNT")+".blob.core.windows.net",
231+
cred, nil,
232+
)
233+
data := []byte("Hello, Azure Storage!")
234+
_, _ = client.UploadBuffer(context.Background(), "uploads", "my-file.txt", data, nil)
235+
}
236+
```
237+
238+
### Rust
239+
240+
Note: Rust uses `DeveloperToolsCredential` as it doesn't have a `DefaultAzureCredential` equivalent.
241+
242+
```rust
243+
use azure_identity::DeveloperToolsCredential;
244+
use azure_storage_blob::{BlobClient, BlobClientOptions};
245+
246+
let credential = DeveloperToolsCredential::new(None)?;
247+
let blob_client = BlobClient::new(
248+
&format!("https://{}.blob.core.windows.net/", std::env::var("AZURE_STORAGE_ACCOUNT")?),
249+
"uploads",
250+
"my-file.txt",
251+
Some(credential),
252+
Some(BlobClientOptions::default()),
253+
)?;
254+
let data = b"Hello, Azure Storage!";
255+
blob_client.upload(None, data.to_vec().into()).await?;
169256
```
170257

171258
## Managed Identity Access

cli/src/internal/assets/ghcp4a-skills/azure-storage/SKILL.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
name: azure-storage
3-
description: Azure Storage Services including Blob Storage, File Shares, Queue Storage, Table Storage, and Data Lake. Provides object storage, SMB file shares, async messaging, NoSQL key-value, and big data analytics capabilities.
3+
description: Azure Storage Services including Blob Storage, File Shares, Queue Storage, Table Storage, and Data Lake. Provides object storage, SMB file shares, async messaging, NoSQL key-value, and big data analytics capabilities. Includes access tiers (hot, cool, archive) and lifecycle management.
44
---
55

66
# Azure Storage Services
@@ -78,3 +78,7 @@ For deep documentation on specific services:
7878
- Blob storage patterns and lifecycle -> [Blob Storage documentation](https://learn.microsoft.com/azure/storage/blobs/storage-blobs-overview)
7979
- File shares and Azure File Sync -> [Azure Files documentation](https://learn.microsoft.com/azure/storage/files/storage-files-introduction)
8080
- Queue patterns and poison handling -> [Queue Storage documentation](https://learn.microsoft.com/azure/storage/queues/storage-queues-introduction)
81+
82+
## Azure SDKs
83+
84+
For building applications that interact with Azure Storage programmatically, Azure provides SDK packages in multiple languages (.NET, Java, JavaScript, Python, Go, Rust). See [SDK Usage Guide](references/sdk-usage.md) for package names, installation commands, and quick start examples.

0 commit comments

Comments
 (0)