All skills
aws avatar

/rds-sqlserver

@748da44

Provides connectivity, authentication, and troubleshooting guidance for Amazon RDS for SQL Server. Applicable when users ask about SSMS times out connecting from EC2, Cannot generate SSPI context with Windows auth, connect RDS SQL Server from Lambda with pymssql, auth_scheme shows NTLM instead of KERBEROS on ECS Fargate, SSM tunnel to RDS SQL Server from laptop, port 1433 security group, TrustServerCertificate=True for localhost tunnels, SPN MSSQLSvc, AWS Managed Microsoft AD, CNAME not RDS endpoint for Kerberos, tds_version='7.4', encryption='require', port-as-string for pymssql, Secrets Manager credential caching in Lambda, error 18456 login failed. Covers Python (pymssql, pyodbc), .NET (Microsoft.Data.SqlClient), Java (JDBC mssql-jdbc), Node.js (tedious), IAM auth via RDS Proxy, and VPC/ECS/EKS/Lambda deployment.

Use this Skill: https://skilld.dev/gh/aws/agent-toolkit-for-aws/rds-sqlserver

This session only. Nothing lands on disk.

referencesnodejs.md

≈1.6k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Node.js — tedious (and mssql wrapper)

Two options:

  • tedious — low-level pure-JS driver (no native deps). Direct control, works in Lambda out of the box.
  • mssql — higher-level wrapper around tedious, adds connection pooling and a friendlier API.

Use mssql for most applications. Use raw tedious only when you need fine-grained control.

Install

npm install tedious        # low-level
npm install mssql          # recommended — wrapper with pooling

Minimal connection with mssql

const sql = require('mssql');
const { SecretsManagerClient, GetSecretValueCommand } = require("@aws-sdk/client-secrets-manager");

async function connect() {
  const sm = new SecretsManagerClient({ region: "us-east-1" });
  const cmd = new GetSecretValueCommand({ SecretId: "rds/sqlserver/app" });
  const { SecretString } = await sm.send(cmd);
  const creds = JSON.parse(SecretString);

  const pool = await sql.connect({
    server: creds.host,
    port: 1433,
    database: creds.dbname,
    user: creds.username,
    password: creds.password,
    options: {
      encrypt: true,               // TLS required in prod
      trustServerCertificate: false,
      connectTimeout: 15000,       // ms
      requestTimeout: 15000,
    },
    pool: {
      max: 10,
      min: 0,
      idleTimeoutMillis: 30000,
    },
  });

  const result = await pool.request().query("SELECT @@VERSION AS v");
  console.log(result.recordset[0].v);
  return pool;
}

Critical tedious/mssql gotchas

Gotcha Why
encrypt: true is default in tedious 16+; not in older versions Check your version
trustServerCertificate: false requires RDS CA bundle See below
port: 1433 as number, NOT string (opposite of pymssql) tedious parses to number
Pool max is per-process Scale down for Lambda
Connection events — listen for 'error' Otherwise silent failures

TLS with cert validation

const fs = require('fs');
const tls = require('tls');

const caBundle = fs.readFileSync('/etc/ssl/certs/global-bundle.pem', 'utf8');
const caList = caBundle.split(/-----END CERTIFICATE-----\n?/)
                       .filter(c => c.trim())
                       .map(c => c + '-----END CERTIFICATE-----\n');

const config = {
  server: creds.host, port: 1433,
  database: creds.dbname,
  user: creds.username, password: creds.password,
  options: {
    encrypt: true,
    trustServerCertificate: false,
    cryptoCredentialsDetails: {
      ca: caList,                  // RDS CA bundle
      minVersion: 'TLSv1.2',
    },
  },
};

Windows auth (NTLM)

tedious has NTLM support (Kerberos is limited):

const config = {
  server: "database-1.corp.example.com",
  port: 1433,
  database: "mydb",
  authentication: {
    type: "ntlm",
    options: {
      userName: "svc-app",
      password: "secret",
      domain: "CORP",
    },
  },
  options: { encrypt: true, trustServerCertificate: false },
};

For proper Kerberos, use a different stack (Java + JDBC, or .NET + IntegratedSecurity).

Lambda pattern

Module-scope pool and secret caching:

const sql = require('mssql');
const { SecretsManagerClient, GetSecretValueCommand } =
  require("@aws-sdk/client-secrets-manager");

const sm = new SecretsManagerClient({});
let poolPromise = null;

async function getPool() {
  if (poolPromise) return poolPromise;
  poolPromise = (async () => {
    const { SecretString } = await sm.send(new GetSecretValueCommand({
      SecretId: process.env.SECRET_ARN,
    }));
    const c = JSON.parse(SecretString);
    return sql.connect({
      server: c.host, port: 1433,
      database: c.dbname, user: c.username, password: c.password,
      options: { encrypt: true, trustServerCertificate: false, connectTimeout: 5000 },
      pool: { max: 2, min: 0, idleTimeoutMillis: 10000 },  // small — Lambda
    });
  })();
  return poolPromise;
}

exports.handler = async (event) => {
  const pool = await getPool();
  const result = await pool.request().query("SELECT 1 AS ok");
  return { statusCode: 200, body: JSON.stringify(result.recordset) };
};

Use @aws-sdk/client-secrets-manager (AWS SDK v3). AWS SDK v2 (aws-sdk package) is deprecated and should not be used for new Lambda code.

For high-concurrency Lambda, use RDS Proxy — see rds-proxy.md.

ECS / EKS

For long-running Node.js services, use mssql with a larger pool:

const pool = await sql.connect({
  server: creds.host, port: 1433,
  database: creds.dbname, user: creds.username, password: creds.password,
  options: { encrypt: true, trustServerCertificate: false },
  pool: {
    max: 20, min: 2,
    idleTimeoutMillis: 600000,    // 10 min
    acquireTimeoutMillis: 30000,
  },
});

// Handle pool errors
pool.on('error', err => {
  console.error('Pool error, reconnecting:', err);
});

// Health check endpoint
app.get('/health', async (req, res) => {
  try {
    await pool.request().query("SELECT 1");
    res.status(200).send("ok");
  } catch (e) {
    res.status(503).send("db unhealthy");
  }
});

Secrets rotation

When Secrets Manager rotates the password, active connections fail with error 18456 (login failed). Handle it:

pool.on('error', async err => {
  if (err.code === 'ELOGIN' || err.number === 18456) {
    console.log('Credentials rotated — rebuilding pool');
    await pool.close();
    poolPromise = null;      // reset the lazy init
  }
});

Verify

const r = await pool.request().query(`
  SELECT encrypt_option, auth_scheme, net_transport
  FROM sys.dm_exec_connections WHERE session_id = @@SPID
`);
console.log(r.recordset[0]);

Raw tedious (without mssql wrapper)

When you need event-driven access:

const { Connection, Request } = require('tedious');

const conn = new Connection({
  server: creds.host,
  options: {
    port: 1433, database: creds.dbname,
    encrypt: true, trustServerCertificate: false,
    connectTimeout: 15000,
  },
  authentication: {
    type: "default",
    options: { userName: creds.username, password: creds.password },
  },
});

conn.on('connect', err => {
  if (err) { console.error('connect failed', err); return; }
  const req = new Request("SELECT 1 AS n", (err, rowCount) => { /* done */ });
  req.on('row', cols => console.log(cols[0].value));
  conn.execSql(req);
});
conn.connect();

No built-in pool — wrap in tarn.js or switch to mssql.

Source: SKILL.md on GitHub

No alerts2mo3 checks · Risk SAFE
  • Gen Agent Trust Hub2mo

    This skill includes some security considerations such as the ingestion of external configuration files and the execution of setup commands with elevated privileges. While these warrant review, they are used within the skill's intended functionality to configure secure database connectivity. The skill actively promotes best practices like using AWS Secrets Manager for credential storage and enforcing TLS 1.2+ for network traffic. See detailed analysis for context.

  • Socket2mo

    No alerts

  • Snyk2mo

    Risk: LOW · No issues

Signed by skilld at 748da44. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated 3 months ago
version
1

README badge

README badge for aws/agent-toolkit-for-aws/rds-sqlserver