<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: AWS Secrets Manager lookup in Qlik Replicate</title>
    <link>https://community.qlik.com/t5/Qlik-Replicate/AWS-Secrets-Manager-lookup/m-p/2543120#M15897</link>
    <description>&lt;P&gt;Hello&amp;nbsp;&lt;a href="https://community.qlik.com/t5/user/viewprofilepage/user-id/140896"&gt;@Vegy&lt;/a&gt;&amp;nbsp;,&lt;/P&gt;
&lt;P data-start="86" data-end="110"&gt;Thanks for the update.&lt;/P&gt;
&lt;P data-start="117" data-end="275"&gt;Replicate 2023.11 has reached its end-of-support (EOS). We recommend using the latest 2025.11 build for the &lt;EM class="Highlight htc1200ddf-813a-4372-ab3a-e0e81c7262c6"&gt;PoC&lt;/EM&gt; to ensure full support and the best results.&lt;/P&gt;
&lt;P data-start="282" data-end="292"&gt;Good luck!&lt;/P&gt;
&lt;P&gt;John.&lt;/P&gt;</description>
    <pubDate>Tue, 17 Feb 2026 00:32:21 GMT</pubDate>
    <dc:creator>john_wang</dc:creator>
    <dc:date>2026-02-17T00:32:21Z</dc:date>
    <item>
      <title>AWS Secrets Manager lookup</title>
      <link>https://community.qlik.com/t5/Qlik-Replicate/AWS-Secrets-Manager-lookup/m-p/2543080#M15894</link>
      <description>&lt;P&gt;Hi,&lt;/P&gt;&lt;P&gt;I'm looking to do a Proof of Concept for using the external credentials addon feature mentioned here&amp;nbsp;&lt;A href="https://help.qlik.com/en-US/replicate/November2025/Content/Replicate/Main/Security/external_credentials.htm" target="_blank" rel="noopener"&gt;https://help.qlik.com/en-US/replicate/November2025/Content/Replicate/Main/Security/external_credentials.htm&lt;/A&gt;&lt;/P&gt;&lt;P&gt;Whilst I have a new addon written and loading successfully I am not quite able to get it working, with the error being "Unable to decrypt password" when I use lookup::key_name in a password field.&amp;nbsp;&lt;/P&gt;&lt;P&gt;Our source is DB2LUW and DB2zOS. I believe these are both supported.&lt;/P&gt;&lt;P&gt;I understand I could reach out to professional services but I wondered if any users had got this working with AWS and if they might be comfortable sharing their .so code?&lt;/P&gt;&lt;P&gt;Cheers&lt;/P&gt;&lt;P&gt;Veg&lt;/P&gt;</description>
      <pubDate>Mon, 16 Feb 2026 11:09:05 GMT</pubDate>
      <guid>https://community.qlik.com/t5/Qlik-Replicate/AWS-Secrets-Manager-lookup/m-p/2543080#M15894</guid>
      <dc:creator>Vegy</dc:creator>
      <dc:date>2026-02-16T11:09:05Z</dc:date>
    </item>
    <item>
      <title>Re: AWS Secrets Manager lookup</title>
      <link>https://community.qlik.com/t5/Qlik-Replicate/AWS-Secrets-Manager-lookup/m-p/2543099#M15896</link>
      <description>&lt;P&gt;I can see that there might be a bug in the version I'm testing with 2023.11 so trying a newer version.&lt;/P&gt;</description>
      <pubDate>Mon, 16 Feb 2026 14:25:13 GMT</pubDate>
      <guid>https://community.qlik.com/t5/Qlik-Replicate/AWS-Secrets-Manager-lookup/m-p/2543099#M15896</guid>
      <dc:creator>Vegy</dc:creator>
      <dc:date>2026-02-16T14:25:13Z</dc:date>
    </item>
    <item>
      <title>Re: AWS Secrets Manager lookup</title>
      <link>https://community.qlik.com/t5/Qlik-Replicate/AWS-Secrets-Manager-lookup/m-p/2543120#M15897</link>
      <description>&lt;P&gt;Hello&amp;nbsp;&lt;a href="https://community.qlik.com/t5/user/viewprofilepage/user-id/140896"&gt;@Vegy&lt;/a&gt;&amp;nbsp;,&lt;/P&gt;
&lt;P data-start="86" data-end="110"&gt;Thanks for the update.&lt;/P&gt;
&lt;P data-start="117" data-end="275"&gt;Replicate 2023.11 has reached its end-of-support (EOS). We recommend using the latest 2025.11 build for the &lt;EM class="Highlight htc1200ddf-813a-4372-ab3a-e0e81c7262c6"&gt;PoC&lt;/EM&gt; to ensure full support and the best results.&lt;/P&gt;
&lt;P data-start="282" data-end="292"&gt;Good luck!&lt;/P&gt;
&lt;P&gt;John.&lt;/P&gt;</description>
      <pubDate>Tue, 17 Feb 2026 00:32:21 GMT</pubDate>
      <guid>https://community.qlik.com/t5/Qlik-Replicate/AWS-Secrets-Manager-lookup/m-p/2543120#M15897</guid>
      <dc:creator>john_wang</dc:creator>
      <dc:date>2026-02-17T00:32:21Z</dc:date>
    </item>
    <item>
      <title>Re: AWS Secrets Manager lookup</title>
      <link>https://community.qlik.com/t5/Qlik-Replicate/AWS-Secrets-Manager-lookup/m-p/2543154#M15900</link>
      <description>&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://community.qlik.com/t5/user/viewprofilepage/user-id/115309"&gt;@john_wang&lt;/a&gt;,&lt;/P&gt;&lt;P&gt;I've passed this on to our product manager.&lt;/P&gt;&lt;P&gt;I got this working last night any wanted to share the code to the community, however, I wanted to confirm it is fine to do so first?&lt;/P&gt;&lt;P&gt;Cheers&lt;/P&gt;&lt;P&gt;Veg&lt;/P&gt;</description>
      <pubDate>Tue, 17 Feb 2026 10:02:10 GMT</pubDate>
      <guid>https://community.qlik.com/t5/Qlik-Replicate/AWS-Secrets-Manager-lookup/m-p/2543154#M15900</guid>
      <dc:creator>Vegy</dc:creator>
      <dc:date>2026-02-17T10:02:10Z</dc:date>
    </item>
    <item>
      <title>Re: AWS Secrets Manager lookup</title>
      <link>https://community.qlik.com/t5/Qlik-Replicate/AWS-Secrets-Manager-lookup/m-p/2543174#M15903</link>
      <description>&lt;P&gt;Hello&amp;nbsp;&lt;a href="https://community.qlik.com/t5/user/viewprofilepage/user-id/140896"&gt;@Vegy&lt;/a&gt;&amp;nbsp;,&lt;/P&gt;
&lt;P&gt;Thank you very much for the update. This resolution will be valuable to all our users. Please feel free to share your code, as long as it doesn’t contain any sensitive or credential-related information.&lt;/P&gt;
&lt;P&gt;Regards,&lt;/P&gt;
&lt;P&gt;John.&lt;/P&gt;</description>
      <pubDate>Tue, 17 Feb 2026 12:41:49 GMT</pubDate>
      <guid>https://community.qlik.com/t5/Qlik-Replicate/AWS-Secrets-Manager-lookup/m-p/2543174#M15903</guid>
      <dc:creator>john_wang</dc:creator>
      <dc:date>2026-02-17T12:41:49Z</dc:date>
    </item>
    <item>
      <title>Re: AWS Secrets Manager lookup</title>
      <link>https://community.qlik.com/t5/Qlik-Replicate/AWS-Secrets-Manager-lookup/m-p/2543175#M15904</link>
      <description>&lt;P&gt;No worries! So just for information I was able to get this working on 2023.11 but as&amp;nbsp;&lt;a href="https://community.qlik.com/t5/user/viewprofilepage/user-id/115309"&gt;@john_wang&lt;/a&gt;&amp;nbsp;says this is EOS. This did also work in 2025.11.&lt;/P&gt;&lt;P&gt;This function accepts both ARN and just secret name, it also handles both string and JSON secrets as long as the secret has a key called password with the correct value in it, i.e. { "password" : "mypassword" }&lt;/P&gt;&lt;P&gt;AWSPasswordProvider.c&lt;/P&gt;&lt;LI-CODE lang="c"&gt;// AWSPasswordProvider.c
// Qlik Replicate external-credentials provider that fetches endpoint passwords
// from AWS Secrets Manager using the AWS CLI.
//
// Key points:
// - Init follows Qlik's sample: AR_AO_INIT -&amp;gt; GET_AR_AO_PASSWORD_PROVIDER_DEF()
//   -&amp;gt; set get_secret_func -&amp;gt; AR_AO_REGISRATION-&amp;gt;register_password_provider(...)
// - get_secret signature matches your header (char *name, ...)
// - Supports plaintext secrets and JSON {"password":"..."}
// - Enforces 4KB max and output buffer size
// - Adds breadcrumbs to /opt/attunity/replicate/tmp/awspp_breadcrumb.txt
//
// Build example:
//   gcc -fPIC -O2 -shared \
//       -I/opt/attunity/replicate/addons/include \
//       -o /opt/attunity/replicate/addons/AWSPasswordProvider.so \
//       /opt/attunity/replicate/addons/AWSPasswordProvider.c
//
// Deploy the .so + addons_def.json to BOTH:
//   /opt/attunity/replicate/addons/
//   /opt/attunity/replicate/endpoint_srv/addons/
//
// In endpoint Password field:  lookup::&amp;lt;secret-id&amp;gt;
//   e.g., lookup::vegtest
//         lookup::arn:aws:secretsmanager:eu-west-2:123456789012:secret:mysecret-ABC

#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;lt;ctype.h&amp;gt;
#include &amp;lt;time.h&amp;gt;
#include &amp;lt;unistd.h&amp;gt;

#include "ar_addon.h"
#include "ar_addon_transformation.h"
#include "ar_addon_password_provider.h"

#include &amp;lt;fcntl.h&amp;gt;
#include &amp;lt;sys/stat.h&amp;gt;

#define MAX_QLIK_SECRET_BYTES (4 * 1024)  // Qlik documented limit

// -------------------- optional breadcrumb for debugging --------------------
#ifndef BREADCRUMB_PATH
#define BREADCRUMB_PATH "/opt/attunity/replicate/tmp/awspp_breadcrumb.txt"
#endif

static void debug_dump_secret(const char* lookup_key, const char* pw) {
    // Debugging of the AWS Secrets Manager can be enabled by setting environment variable DEBUG_AWS_ADDON=1 in the replicate process.
    // This will create/append to /opt/attunity/replicate/tmp/awspp_secret_dbg.txt with lines like:
    // 2026-02-16T19:00:00Z pid=1234 proc=replicate_task lookup::vegtest PLAIN="mysecret" HEX=6d79736563726574"
    // Therefore use should be used with care and only in non-production environments, ensuring the tmp file is securely handled and deleted after use. 
    // The hex dump can help confirm if there are any hidden characters or encoding issues in the retrieved secret.
    const char* dbg = getenv("DEBUG_AWS_ADDON");
    if (!dbg || strcmp(dbg, "1") != 0) return;

    // Ensure the directory exists with permissive mode for both processes
    mkdir("/opt/attunity/replicate/tmp", 0777);

    int fd = open("/opt/attunity/replicate/tmp/awspp_secret_dbg.txt",
                  O_WRONLY | O_CREAT | O_APPEND, 0600);
    if (fd &amp;lt; 0) return;

    // Timestamp (UTC)
    time_t now = time(NULL);
    struct tm tmv; gmtime_r(&amp;amp;now, &amp;amp;tmv);
    char ts[32]; strftime(ts, sizeof(ts), "%Y-%m-%dT%H:%M:%SZ", &amp;amp;tmv);

    // Process name (best effort)
    char comm[64] = {0};
    FILE *fc = fopen("/proc/self/comm", "r");
    if (fc) { fgets(comm, sizeof(comm), fc); fclose(fc);
              size_t n = strlen(comm);
              if (n &amp;amp;&amp;amp; (comm[n-1]=='\n' || comm[n-1]=='\r')) comm[n-1] = '\0'; }
    else { strncpy(comm, "unknown", sizeof(comm)-1); }

    // Plaintext line
    dprintf(fd, "%s pid=%d proc=%s key=%s PLAIN=\"%s\"\n",
            ts, (int)getpid(), comm, (lookup_key ? lookup_key : "(null)"),
            (pw ? pw : "(null)"));

    // Hex dump line
    if (pw) {
        dprintf(fd, "%s pid=%d proc=%s key=%s HEX=",
                ts, (int)getpid(), comm, (lookup_key ? lookup_key : "(null)"));
        for (const unsigned char *p=(const unsigned char*)pw; *p; ++p)
            dprintf(fd, "%02x", *p);
        dprintf(fd, "\n");
    }

    close(fd);
}

static void write_breadcrumb(const char* tag)
{
    // Writes "YYYY-MM-DDTHH:MM:SSZ pid=... proc=... :: &amp;lt;tag&amp;gt;"
    char ts[32];
    time_t now = time(NULL);
    struct tm tmv;
    gmtime_r(&amp;amp;now, &amp;amp;tmv);
    strftime(ts, sizeof(ts), "%Y-%m-%dT%H:%M:%SZ", &amp;amp;tmv);

    char comm[64] = {0};
    FILE *fc = fopen("/proc/self/comm", "r");
    if (fc) {
        fgets(comm, sizeof(comm), fc);
        fclose(fc);
        size_t n = strlen(comm);
        if (n &amp;amp;&amp;amp; (comm[n-1] == '\n' || comm[n-1] == '\r')) comm[n-1] = '\0';
    } else {
        strncpy(comm, "unknown", sizeof(comm)-1);
    }

    FILE *f = fopen(BREADCRUMB_PATH, "a");
    if (!f) return; // silently ignore if unwritable
    fprintf(f, "%s pid=%d proc=%s :: %s\n", ts, (int)getpid(), comm, tag);
    fclose(f);
}

// -------------------- helpers --------------------

static void trim_ws(char *s) {
    if (!s) return;
    char *p = s; while (*p &amp;amp;&amp;amp; isspace((unsigned char)*p)) p++;
    size_t len = strlen(p);
    memmove(s, p, len + 1);
    while (len &amp;gt; 0 &amp;amp;&amp;amp; isspace((unsigned char)s[len - 1])) { s[--len] = '\0'; }
}

static void unquote_if_wrapped(char *s) {
    size_t n = strlen(s);
    if (n &amp;gt;= 2 &amp;amp;&amp;amp; s[0] == '"' &amp;amp;&amp;amp; s[n-1] == '"') {
        memmove(s, s+1, n-2);
        s[n-2] = '\0';
    }
    n = strlen(s);
    if (n &amp;gt;= 2 &amp;amp;&amp;amp; s[0] == '\'' &amp;amp;&amp;amp; s[n-1] == '\'') {
        memmove(s, s+1, n-2);
        s[n-2] = '\0';
    }
}

static int starts_with_json_obj(const char *s) {
    if (!s) return 0;
    while (*s &amp;amp;&amp;amp; isspace((unsigned char)*s)) s++;
    return (*s == '{');
}

// naive extractor: finds "key":"value"
static int extract_json_field(const char* json, const char* key, char* out, int out_len) {
    char pattern[128];
    snprintf(pattern, sizeof(pattern), "\"%s\"", key);
    const char* p = strstr(json, pattern);
    if (!p) return 0;
    p = strchr(p, ':'); if (!p) return 0; p++;
    while (*p == ' ') p++;
    if (*p != '\"') return 0;
    p++;
    int i = 0;
    while (*p &amp;amp;&amp;amp; *p != '\"' &amp;amp;&amp;amp; i &amp;lt; out_len - 1) { out[i++] = *p++; }
    out[i] = '\0';
    return (i &amp;gt; 0);
}

// escape single quotes for safe single-quoted shell args
static void shell_escape_single_quotes(const char* in, char* out, size_t out_len) {
    size_t o = 0;
    for (size_t i = 0; in[i] &amp;amp;&amp;amp; o + 4 &amp;lt; out_len; i++) {
        if (in[i] == '\'') {
            const char *esc = "'\\''";  // end, escaped quote, reopen
            size_t l = strlen(esc);
            if (o + l &amp;gt;= out_len) break;
            memcpy(out + o, esc, l); o += l;
        } else {
            out[o++] = in[i];
        }
    }
    if (o &amp;lt; out_len) out[o] = '\0';
}

// run command, capture stdout into malloc'ed buffer; caller free()
static char* run_cmd_capture_all(const char* cmd) {
    FILE *fp = popen(cmd, "r");
    if (!fp) return NULL;
    size_t cap = 4096, len = 0;
    char *buf = (char*)malloc(cap);
    if (!buf) { pclose(fp); return NULL; }

    size_t n;
    while ((n = fread(buf + len, 1, cap - len, fp)) &amp;gt; 0) {
        len += n;
        if (len == cap) {
            cap &amp;lt;&amp;lt;= 1;
            char *tmp = (char*)realloc(buf, cap);
            if (!tmp) { free(buf); pclose(fp); return NULL; }
            buf = tmp;
        }
    }
    pclose(fp);
    buf[len] = '\0';
    return buf;
}

// parse "&amp;lt;id&amp;gt;@&amp;lt;stage&amp;gt;" -&amp;gt; id, stage (stage optional)
static void parse_id_and_stage(const char *lookup_key, char *id, size_t id_len, char *stage, size_t stage_len) {
    const char *at = strrchr(lookup_key, '@');
    if (at &amp;amp;&amp;amp; at != lookup_key) {
        size_t l_id = (size_t)(at - lookup_key);
        if (l_id &amp;gt;= id_len) l_id = id_len - 1;
        memcpy(id, lookup_key, l_id); id[l_id] = '\0';
        strncpy(stage, at + 1, stage_len - 1); stage[stage_len - 1] = '\0';
    } else {
        strncpy(id, lookup_key, id_len - 1); id[id_len - 1] = '\0';
        stage[0] = '\0';
    }
}

// -------------------- forward declaration (matches header) --------------------
static AR_ADDONS_STATUS get_secret(
    char *name,                       // MUST be non-const to match get_secret_func typedef
    const char *lookup_key,
    char *secret,
    int secret_len,
    char *principal,
    int principal_len);

// -------------------- get_secret (core) --------------------
static AR_ADDONS_STATUS get_secret(
    char *name,
    const char *lookup_key,
    char *secret,
    int secret_len,
    char *principal,
    int principal_len)
{
    (void)name; (void)principal; (void)principal_len;

    write_breadcrumb("get_secret: entry");

    if (!lookup_key || !secret || secret_len &amp;lt;= 1) {
        if (AR_AO_LOG &amp;amp;&amp;amp; AR_AO_LOG-&amp;gt;log_error)
            AR_AO_LOG-&amp;gt;log_error("[AWSPasswordProvider] Invalid input args (lookup_key/secret)");
        return AR_ADDONS_STATUS_FAILED;
    }

    char secret_id[1024], stage[128];
    parse_id_and_stage(lookup_key, secret_id, sizeof(secret_id), stage, sizeof(stage));

    // Build AWS CLI command using absolute path for safety across processes.
    char id_esc[2048], stage_esc[256], cmd[4096];
    shell_escape_single_quotes(secret_id, id_esc, sizeof(id_esc));
    shell_escape_single_quotes(stage,     stage_esc, sizeof(stage_esc));

    if (stage[0]) {
        snprintf(cmd, sizeof(cmd),
            "aws secretsmanager get-secret-value "
            "--secret-id '%s' --version-stage '%s' --query SecretString --output text 2&amp;gt;&amp;amp;1",
            id_esc, stage_esc);
    } else {
        snprintf(cmd, sizeof(cmd),
            "aws secretsmanager get-secret-value "
            "--secret-id '%s' --query SecretString --output text 2&amp;gt;&amp;amp;1",
            id_esc);
    }

    if (AR_AO_LOG &amp;amp;&amp;amp; AR_AO_LOG-&amp;gt;log_trace)
        AR_AO_LOG-&amp;gt;log_trace("[AWSPasswordProvider] Fetching SecretString for key '%s'%s",
                             secret_id, stage[0] ? " (stage specified)" : "");

    char *out = run_cmd_capture_all(cmd);
    if (!out) {
        if (AR_AO_LOG &amp;amp;&amp;amp; AR_AO_LOG-&amp;gt;log_error)
            AR_AO_LOG-&amp;gt;log_error("[AWSPasswordProvider] AWS CLI exec failed for key '%s'", secret_id);
        return AR_ADDONS_STATUS_FAILED;
    }

    trim_ws(out);

    if (strlen(out) == 0 || strcmp(out, "None") == 0 || strcmp(out, "null") == 0) {
        free(out);
        if (AR_AO_LOG &amp;amp;&amp;amp; AR_AO_LOG-&amp;gt;log_error)
            AR_AO_LOG-&amp;gt;log_error("[AWSPasswordProvider] Empty SecretString for key '%s'", secret_id);
        return AR_ADDONS_STATUS_FAILED;
    }

    char pw[MAX_QLIK_SECRET_BYTES + 1] = {0};

    if (starts_with_json_obj(out)) {
        if (!extract_json_field(out, "password", pw, sizeof(pw))) {
            free(out);
            if (AR_AO_LOG &amp;amp;&amp;amp; AR_AO_LOG-&amp;gt;log_error)
                AR_AO_LOG-&amp;gt;log_error("[AWSPasswordProvider] JSON SecretString missing 'password' for key '%s'", secret_id);
            return AR_ADDONS_STATUS_FAILED;
        }
    } else {
        // plaintext support
        strncpy(pw, out, MAX_QLIK_SECRET_BYTES);
        pw[MAX_QLIK_SECRET_BYTES] = '\0';
        trim_ws(pw);
        unquote_if_wrapped(pw);
    }

    free(out);
    trim_ws(pw);

    size_t pw_len = strlen(pw);
    if (pw_len == 0) {
        if (AR_AO_LOG &amp;amp;&amp;amp; AR_AO_LOG-&amp;gt;log_error)
            AR_AO_LOG-&amp;gt;log_error("[AWSPasswordProvider] Resolved empty password for key '%s'", secret_id);
        return AR_ADDONS_STATUS_FAILED;
    }

    // Size guards
    if (pw_len &amp;gt; MAX_QLIK_SECRET_BYTES) {
        if (AR_AO_LOG &amp;amp;&amp;amp; AR_AO_LOG-&amp;gt;log_error)
            AR_AO_LOG-&amp;gt;log_error("[AWSPasswordProvider] Password length (%zu) exceeds 4KB limit for key '%s'",
                                 pw_len, secret_id);
        return AR_ADDONS_STATUS_FAILED;
    }
    if (pw_len &amp;gt;= (size_t)secret_len) {
        if (AR_AO_LOG &amp;amp;&amp;amp; AR_AO_LOG-&amp;gt;log_error)
            AR_AO_LOG-&amp;gt;log_error("[AWSPasswordProvider] Password length (%zu) exceeds output buffer (%d) for key '%s'",
                                 pw_len, secret_len, secret_id);
        return AR_ADDONS_STATUS_FAILED;
    }

    memcpy(secret, pw, pw_len);
    secret[pw_len] = '\0';

    if (AR_AO_LOG &amp;amp;&amp;amp; AR_AO_LOG-&amp;gt;log_trace)
        AR_AO_LOG-&amp;gt;log_trace("[AWSPasswordProvider] get_secret completed for key '%s' (pw_len=%zu)",
                             secret_id, pw_len);

    debug_dump_secret(secret_id, pw);   // &amp;lt;--- NEW: plaintext + hex dump
    memcpy(secret, pw, pw_len);
    secret[pw_len] = '\0';

    write_breadcrumb("get_secret: success");
    return AR_ADDONS_STATUS_SUCCESS;
}

// -------------------- ar_addon_init (Qlik sample pattern) --------------------
// EXACT pattern from Qlik sample: AR_AO_INIT -&amp;gt; GET_AR_AO_PASSWORD_PROVIDER_DEF
// -&amp;gt; set get_secret_func -&amp;gt; AR_AO_REGISRATION-&amp;gt;register_password_provider(...)
AR_AO_EXPORTED int ar_addon_init(AR_ADDON_CONTEXT *context)
{
    AR_AO_PASSWORD_PROVIDER_DEF *passwordProviderdef = NULL;

    AR_AO_INIT(context);  // required framework init

    passwordProviderdef = GET_AR_AO_PASSWORD_PROVIDER_DEF();
    if (!passwordProviderdef) {
        write_breadcrumb("init: provider=NULL");
        if (AR_AO_LOG &amp;amp;&amp;amp; AR_AO_LOG-&amp;gt;log_error)
            AR_AO_LOG-&amp;gt;log_error("[AWSPasswordProvider] ar_addon_init: GET_AR_AO_PASSWORD_PROVIDER_DEF() returned NULL");
        return -1;
    }

    // Wire our implementation; signature matches header (char *name, ...)
    passwordProviderdef-&amp;gt;get_secret_func = get_secret;

    // **Critical** registration step (fixes "Password provider is not registered")
    AR_AO_REGISRATION-&amp;gt;register_password_provider(passwordProviderdef);

    write_breadcrumb("init: provider registered");
    if (AR_AO_LOG &amp;amp;&amp;amp; AR_AO_LOG-&amp;gt;log_trace)
        AR_AO_LOG-&amp;gt;log_trace("[AWSPasswordProvider] ar_addon_init: provider registered");

    return 0;
}&lt;/LI-CODE&gt;&lt;P&gt;As mentioned on the Qlik documentation you need to update your addons_def.json&lt;/P&gt;&lt;LI-CODE lang="markup"&gt;{
    "addons": [{
      "name": "AWSPasswordProvider",
      "type": "STARTUP",
      "lib_path": "/opt/attunity/replicate/addons/AWSPasswordProvider.so",
      "init_function": "ar_addon_init"
    }]
}&lt;/LI-CODE&gt;&lt;P&gt;You then need to compile this in to a library file. As we run Qlik in docker on linux I just added this to our Dockerfile&lt;/P&gt;&lt;LI-CODE lang="markup"&gt;# --- copy provider source and compile ---
COPY ./qlik/AWSPasswordProvider.c /tmp/AWSPasswordProvider.c

# Qlik headers live under replicate/addons/include
RUN gcc -fPIC -O2 -shared \
    -I $QLIK_REPLICATE_BASE_DIR/addons/include \
    -o $QLIK_REPLICATE_BASE_DIR/addons/AWSPasswordProvider.so \
    /tmp/AWSPasswordProvider.c

# --- register the addon ---
COPY ./qlik/addons_def.json $QLIK_REPLICATE_BASE_DIR/addons/addons_def.json&lt;/LI-CODE&gt;&lt;P&gt;There are some environment specific things to consider:&lt;/P&gt;&lt;P&gt;We run our qlik in a FARGATE service in AWS, this means as long as the ECS task running the container has the correct permissions to AWS Secrets then there is not much else to do. If you run Qlik on Windows or Linux outside of AWS you would have to consider how you allow the system to access AWS.&lt;/P&gt;&lt;P&gt;This is only my initial code, I need to add some additonal checks like handing when the secret name does not exist.&lt;/P&gt;&lt;P&gt;Happy to answer any questions or take feedback to improve&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Cheers&lt;/P&gt;&lt;P&gt;Veg&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 17 Feb 2026 13:00:16 GMT</pubDate>
      <guid>https://community.qlik.com/t5/Qlik-Replicate/AWS-Secrets-Manager-lookup/m-p/2543175#M15904</guid>
      <dc:creator>Vegy</dc:creator>
      <dc:date>2026-02-17T13:00:16Z</dc:date>
    </item>
    <item>
      <title>Re: AWS Secrets Manager lookup</title>
      <link>https://community.qlik.com/t5/Qlik-Replicate/AWS-Secrets-Manager-lookup/m-p/2543179#M15905</link>
      <description>&lt;P&gt;Hello&amp;nbsp;&lt;a href="https://community.qlik.com/t5/user/viewprofilepage/user-id/140896"&gt;@Vegy&lt;/a&gt;&amp;nbsp;,&lt;/P&gt;
&lt;P&gt;Many thanks for your outstanding support! Your sharing and efforts are greatly appreciated.&lt;/P&gt;
&lt;P&gt;John.&lt;/P&gt;</description>
      <pubDate>Tue, 17 Feb 2026 13:19:01 GMT</pubDate>
      <guid>https://community.qlik.com/t5/Qlik-Replicate/AWS-Secrets-Manager-lookup/m-p/2543179#M15905</guid>
      <dc:creator>john_wang</dc:creator>
      <dc:date>2026-02-17T13:19:01Z</dc:date>
    </item>
  </channel>
</rss>

