Get IP address from Azure Private Endpoint using Pulumi TypeScript API - pulumi

I have a Private Endpoint created in my Azure subscription. If I look into the Azure Portal I can see that the private IP assigned to my Private Endpoint NIC is 10.0.0.4.
But how can I get the IP address value using the Pulumi TypeScript API, so I can use it in my scripts?
const privateEndpoint = new network.PrivateEndpoint("privateEndpoint", {
privateLinkServiceConnections: [{
groupIds: ["sites"],
name: "privateEndpointLink1",
privateLinkServiceId: backendApp.id,
}],
resourceGroupName: resourceGroup.name,
subnet: {
id: subnet.id,
}
});
export let ipc = privateEndpoint.networkInterfaces.apply(networkInterfaces => networkInterfaces[0].ipConfigurations)
console.log(ipc)
This is the current output for that ipc variable:
OutputImpl {
__pulumiOutput: true,
resources: [Function (anonymous)],
allResources: [Function (anonymous)],
isKnown: Promise { <pending> },
isSecret: Promise { <pending> },
promise: [Function (anonymous)],
toString: [Function (anonymous)],
toJSON: [Function (anonymous)]
}

You can't log a pulumi Output until its resolved, so if you change your code slightly, this will work:
const privateEndpoint = new network.PrivateEndpoint("privateEndpoint", {
privateLinkServiceConnections: [{
groupIds: ["sites"],
name: "privateEndpointLink1",
privateLinkServiceId: backendApp.id,
}],
resourceGroupName: resourceGroup.name,
subnet: {
id: subnet.id,
}
});
export let ipc = privateEndpoint.networkInterfaces.apply(networkInterfaces => console.log(networkInterfaces[0].ipConfigurations))

I found the solution to my problem.
I was publishing a Static Web App to an incorrect Private DNS Zone. Correct one should be privatelink.1.azurestaticapps.net.
Once that was fixed I got the data that I needed.
{
name: 'config1',
privateDnsZoneId: '/subscriptions/<subscription>/resourceGroups/rg-static-webappc0811aae/providers/Microsoft.Network/privateDnsZones/privatelink.1.azurestaticapps.net',
recordSets: [
{
fqdn: 'thankful-sand-084c7860f.privatelink.1.azurestaticapps.net',
ipAddresses: [Array],
provisioningState: 'Succeeded',
recordSetName: 'thankful-sand-084c7860f',
recordType: 'A',
ttl: 10
}
]
}
{
fqdn: 'thankful-sand-084c7860f.privatelink.1.azurestaticapps.net',
ipAddresses: [ '10.0.0.4' ],
provisioningState: 'Succeeded',
recordSetName: 'thankful-sand-084c7860f',
recordType: 'A',
ttl: 10
}

Related

How to get the ARN of a codepipeline inside of the same CDK stack

I am trying to set up a notification rule as part of a code pipeline in a CDK stack.
Note this is NOT a CDK pipeline but a CDK stack that is setting up a AWS CodePipeline.
In order to create a CfnNotificationRule I must pass in the ARN of the CodePipeline as the resource parameter. In the sample code below I've hardcoded the ARN as TARGET_ARN
However, I would like to provide this dynamically.
How do I provide the ARN that CDK generates for my-pipeline to the CfnNotificationRule constructor?
const codepipeline = require('#aws-cdk/aws-codepipeline');
class PipelineStack extends cdk.Stack {
constructor(scope, id, props) {
super(scope, id, props);
//I want the ARN of this pipeline in TARGET_ARN
new codepipeline.Pipeline(this, 'Pipeline', {
crossAccountKeys: false,
pipelineName: "my-pipeline",
stages: [{
stageName: 'Source',
},
{
stageName: 'Build',
},
{
stageName: 'Deploy',
]
}
]
})
const AWS_SLACK_CHATBOT_ARN = 'arn:aws:chatbot::111111111111:chat-configuration/slack-channel/my-slack-channel'
const TARGET_ARN = 'arn:aws:codepipeline:us-east-2:111111111111:my-pipeline'
const notes = new notifications.CfnNotificationRule(this, 'my-dev-slack', {
detailType: "FULL",
name: "my-dev-slack",
eventTypeIds: [
"codepipeline-pipeline-action-execution-succeeded",
"codepipeline-pipeline-action-execution-failed",
"codepipeline-pipeline-stage-execution-failed"
],
targets: [{
targetType: "AWSChatbotSlack",
targetAddress: AWS_SLACK_CHATBOT_ARN
}],
resource: TARGET_ARN
})
}
}
Initialise the pipeline as a local variable and then you can use its internal methods after, for example your new code would look like this (I noticed you had a bracket [ under stageName: 'Deploy', which was causing the code note to compile so I have removed it in my example )
const myPipeline = new codepipeline.Pipeline(this, 'Pipeline', {
crossAccountKeys: false,
pipelineName: "my-pipeline",
stages: [{
stageName: 'Source',
},
{
stageName: 'Build',
},
{
stageName: 'Deploy',
}]
})
myPipeline.pipelineArn
myPipeline.pipelineArn will give you the ARN

Payment token not in response

==== SOLVED ====
Problem is solved. Adyen wants you to send the whole string as an object. JSON.parse(token). Make sure Google pay is enabled in the Adyen platform.
================
I'm working on transactions with Actions on Google and integration Google Pay. I followed all steps according to the documentation of Actions on Google.
To propose an order I send the following snippet seen below.
Notes:
gateway value is replaced for security reasons.
gatewayMerchantId value is replaced for security reasons.
I'm using a registered gateway.
I have not yet registered as Google partner though the business console so I have no access to the production API.
// Handle order with Google Pay.
conv.ask(new TransactionDecision({
orderOptions: {
requestDeliveryAddress: true,
userInfoOptions: {
userInfoProperties: [
'EMAIL',
],
},
},
paymentParameters: {
googlePaymentOption: {
facilitationSpec: JSON.stringify({
apiVersion: 2,
apiVersionMinor: 0,
environment: 'TEST',
merchantInfo: {
merchantName: 'Example Merchant',
merchantId: '12345678901234567890',
},
allowedPaymentMethods: [
{
type: 'CARD',
parameters: {
allowedAuthMethods: ['PAN_ONLY', 'CRYPTOGRAM_3DS'],
allowedCardNetworks: [
'AMEX', 'DISCOVER', 'JCB', 'MASTERCARD', 'VISA',
],
},
tokenizationSpecification: {
type: 'PAYMENT_GATEWAY',
parameters: {
'gateway': 'my_gateway',
'gatewayMerchantId': 'my_gateway_id',
},
},
},
],
transactionInfo: {
totalPriceStatus: 'FINAL',
totalPrice: prodPriceInclBtwInMicros.toString(),
currencyCode: 'EUR',
},
}),
},
},
presentationOptions: {
actionDisplayName: 'PLACE_ORDER',
},
order: order,
}));
The intent that handles the transaction decision value obtains the following arg value:
const arg = conv.arguments.get('TRANSACTION_DECISION_VALUE');
{
'#type': 'type.googleapis.com/google.actions.transactions.v3.TransactionDecisionValue',
transactionDecision: 'ORDER_ACCEPTED',
order: {
googleOrderId: '02458320178127324049',
merchantOrderId: 'example',
userVisibleOrderId: 'example',
buyerInfo: {
email: 'example#example.com',
firstName: 'example',
lastName: 'example',
displayName: 'example example'
},
createTime: '2020-07-21T10:59:16.624Z',
lastUpdateTime: '2020-07-21T10:59:16.624Z',
transactionMerchant: { name: 'Example Merchant' },
contents: { lineItems: [Array] },
priceAttributes: [ [Object], [Object], [Object] ],
paymentData: { paymentResult: [Object], paymentInfo: [Object] },
purchase: {
status: 'CREATED',
type: 'RETAIL',
userVisibleStatusLabel: 'CREATED'
},
vertical: {
'#type': 'type.googleapis.com/google.actions.orders.v3.verticals.purchase.PurchaseOrderExtension',
status: 'CREATED',
type: 'RETAIL',
userVisibleStatusLabel: 'CREATED'
}
}
}
According to [Adyen][1] I should provide the payment token: 'Get the token from PaymentData response from the Google Pay API.' [Google][2] states that the token will be returned in a response object after the user approves the payment. This is certainly not the case as can be seen in the `arg` object.
By digging deeper into the paymentData, we get the following values:
{
paymentResult: {
googlePaymentData: '{"signature":"MEYCIQDS8Tiu9bprWqamQ24oNx+Wa43Wg6Vi3sP5PArDeOtOEAIhAOBqe4sQvN5tD390qWzDn9DIgwA8gjS8ajynrusOix6O","protocolVersion":"ECv1","signedMessage":"{\\"encryptedMessage\\":\\"Some_tokens_IUHASIDHUSAGFUAHS\\",\\"ephemeralPublicKey\\":\\"SOMEKEYSASD\\\\u003d\\",\\"tag\\":\\"SOMETAG_OIASJDJSOIJ\\\\u003d\\"}"}'
},
paymentInfo: {
paymentMethodDisplayInfo: {
paymentType: 'PAYMENT_CARD',
paymentMethodDisplayName: 'Visa •••• 1234'
},
paymentMethodProvenance: 'PAYMENT_METHOD_PROVENANCE_GOOGLE'
}
}
Still no token returned in the response... This will be necessary for the gateway.
Does anyone know how to resolve this? Or does this have to with the production Transaction API?
Any help is appreciated.
[1]: https://docs.adyen.com/payment-methods/google-pay/api-only
[2]: https://developers.google.com/pay/api/web/reference/response-objects#PaymentData

Get EIP as output from aws-cdk generated VPC definition

There is a vpc definition via
const vpc = new ec2.Vpc(this, 'SomeVPC', {
cidr: '10.0.0.0/16',
maxAzs: 2,
});
Under the hood it creates 2 EIP for NAT gateways
"SomeVPCPublicSubnet1EIP58E3D6C5": {
"Type": "AWS::EC2::EIP",
"Properties": {
"Domain": "vpc"
}
}
how to grab the references to them and export it via CfnOutput? Something like this:
new CfnOutput(this, "ExternalIPOutput", {value: <some magic call to get SomeVPCPublicSubnet1EIP58E3D6C5.ref()>})
It's been a while but I faced this issue today and this is how I managed to handle it and grab the EIP -
Code Snippet:
// Create new VPC
const vpc = new ec2.Vpc(this, 'VPC', {
cidr: props.customCidr,
maxAzs: 2,
subnetConfiguration: [
{
name: 'Private',
subnetType: ec2.SubnetType.PRIVATE
},
{
name: 'Public',
subnetType: ec2.SubnetType.PUBLIC
}
]
});
// Get Elastic IP
vpc.publicSubnets.forEach((subnet, index) => {
// Find the Elastic IP
const EIP = subnet.node.tryFindChild('EIP') as ec2.CfnEIP
new cdk.CfnOutput(this, `output-eip-${index}`, { value: EIP.ref });
})
Output:

Setting up AWS IoT using Serverless Framework for Multiple IoT Devices

My goal is to create a system on AWS using the serverless framework for multiple IoT devices to send JSON payloads to AWS IoT, which in turn will be saved to DynamoDB.
I am very new to using AWS outside of creating EC2 servers and this is my first project using the serverless framework.
After referring to an example, the modified version that I came up with is posted below.
Problem: It appears that the example is for just 1 device to connect to AWS IoT, which I concluded from the hardcoded IoT Thing certificate being used, such as
SensorPolicyPrincipalAttachmentCert:
Type: AWS::IoT::PolicyPrincipalAttachment
Properties:
PolicyName: { Ref: SensorThingPolicy }
Principal: ${{custom.iotCertificateArn}}
SensorThingPrincipalAttachmentCert:
Type: "AWS::IoT::ThingPrincipalAttachment"
Properties:
ThingName: { Ref: SensorThing }
Principal: ${self:custom.iotCertificateArn}
If this conclusion is correct that serverless.yml is configured for only 1 Thing, then what modifications can we make such that more than 1 Thing can be used?
Maybe setup all the Things outside of serverless.yaml? Which means removing just SensorPolicyPrincipalAttachmentCert and SensorThingPrincipalAttachmentCert?
Also, how should we set the Resource property to in SensorThingPolicy? They are currently set to "*", is this too broard? Or is there a way to limit to just Things.
serverless.yml
service: garden-iot
provider:
name: aws
runtime: nodejs6.10
region: us-east-1
# load custom variables from a file
custom: ${file(./vars-dev.yml)}
resources:
Resources:
LocationData:
Type: AWS::DynamoDB::Table
Properties:
TableName: location-data-${opt:stage}
AttributeDefinitions:
-
AttributeName: ClientId
AttributeType: S
-
AttributeName: Timestamp
AttributeType: S
KeySchema:
-
AttributeName: ClientId
KeyType: HASH
-
AttributeName: Timestamp
KeyType: RANGE
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
SensorThing:
Type: AWS::IoT::Thing
Properties:
AttributePayload:
Attributes:
SensorType: soil
SensorThingPolicy:
Type: AWS::IoT::Policy
Properties:
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action: ["iot:Connect"]
Resource: ["${self:custom.sensorThingClientResource}"]
- Effect: "Allow"
Action: ["iot:Publish"]
Resource: ["${self:custom.sensorThingSoilTopicResource}"]
SensorPolicyPrincipalAttachmentCert:
Type: AWS::IoT::PolicyPrincipalAttachment
Properties:
PolicyName: { Ref: SensorThingPolicy }
Principal: ${{custom.iotCertificateArn}}
SensorThingPrincipalAttachmentCert:
Type: "AWS::IoT::ThingPrincipalAttachment"
Properties:
ThingName: { Ref: SensorThing }
Principal: ${self:custom.iotCertificateArn}
IoTRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: Allow
Principal:
Service:
- iot.amazonaws.com
Action:
- sts:AssumeRole
IoTRolePolicies:
Type: AWS::IAM::Policy
Properties:
PolicyName: IoTRole_Policy
PolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: Allow
Action:
- dynamodb:PutItem
Resource: "*"
-
Effect: Allow
Action:
- lambda:InvokeFunction
Resource: "*"
Roles: [{ Ref: IoTRole }]
EDIT 05/09/2018: I've found this blog post, which describes my approach pretty well: Ensure Secure Communication with AWS IoT Core Using the Certificate Vending Machine Reference Application
--
You could take a look at Just-in-Time Provisioning or build your own solution based on Programmatic Provisioning.
I have dealt with this topic many times and had to realize that it depends a lot on the use case, which makes more sense. Also security is an aspect to keep an eye on. You don't want to have a public API responsible for JIT device registration accessible by the whole Internet.
A simple Programmatic Provisioning-based scenario could look like this: You build a thing (maybe a sensor), which should be abled to connect to AWS IoT and have an in-house provisioning process.
Simple provisioning process:
Thing built
Thing has a serial number
Thing registers itself via an internal server
The registration code running on the server could look something like this (JS + AWS JS SDK):
// Modules
const AWS = require('aws-sdk')
// AWS
const iot = new AWS.Iot({ region: process.env.region })
// Config
const templateBodyJson = require('./register-thing-template-body.json')
// registerThing
const registerThing = async ({ serialNumber = null } = {}) => {
if (!serialNumber) throw new Error('`serialNumber` required!')
const {
certificateArn = null,
certificateId = null,
certificatePem = null,
keyPair: {
PrivateKey: privateKey = null,
PublicKey: publicKey = null
} = {}
} = await iot.createKeysAndCertificate({ setAsActive: true }).promise()
const registerThingParams = {
templateBody: JSON.stringify(templateBodyJson),
parameters: {
ThingName: serialNumber,
SerialNumber: serialNumber,
CertificateId: certificateId
}
}
const { resourceArns = null } = await iot.registerThing(registerThingParams).promise()
return {
certificateArn,
certificateId,
certificatePem,
privateKey,
publicKey,
resourceArns
}
}
const unregisterThing = async ({ serialNumber = null } = {}) => {
if (!serialNumber) throw new Error('`serialNumber` required!')
try {
const thingName = serialNumber
const { principals: thingPrincipals } = await iot.listThingPrincipals({ thingName }).promise()
const certificates = thingPrincipals.map((tp) => ({ certificateId: tp.split('/').pop(), certificateArn: tp }))
for (const { certificateId, certificateArn } of certificates) {
await iot.detachThingPrincipal({ thingName, principal: certificateArn }).promise()
await iot.updateCertificate({ certificateId, newStatus: 'INACTIVE' }).promise()
await iot.deleteCertificate({ certificateId, forceDelete: true }).promise()
}
await iot.deleteThing({ thingName }).promise()
return {
deleted: true,
thingPrincipals
}
} catch (err) {
// Already deleted!
if (err.code && err.code === 'ResourceNotFoundException') {
return {
deleted: true,
thingPrincipals: []
}
}
throw err
}
}
register-thing-template-body.json:
{
"Parameters": {
"ThingName": {
"Type": "String"
},
"SerialNumber": {
"Type": "String"
},
"CertificateId": {
"Type": "String"
}
},
"Resources": {
"thing": {
"Type": "AWS::IoT::Thing",
"Properties": {
"ThingName": {
"Ref": "ThingName"
},
"AttributePayload": {
"serialNumber": {
"Ref": "SerialNumber"
}
},
"ThingTypeName": "NewDevice",
"ThingGroups": ["NewDevices"]
}
},
"certificate": {
"Type": "AWS::IoT::Certificate",
"Properties": {
"CertificateId": {
"Ref": "CertificateId"
}
}
},
"policy": {
"Type": "AWS::IoT::Policy",
"Properties": {
"PolicyName": "DefaultNewDevicePolicy"
}
}
}
}
Make sure you got all the "NewDevice" Thing types, groups and policies in place. Also keep in mind ThingName = SerialNumber (important for unregisterThing).

Error while setting up Extjs Rest Proxy Create function

I am using Rest proxy in Extjs Model as:
Ext.define('ThemeApp.model.peopleModel', {
extend: 'Ext.data.Model', fields: [
{ name: 'userId' },
{ name: 'title' },
{ name: 'body'}
],
proxy: {
type: 'rest',
format: 'json',
limitParam:"",
filterParam: "",
startParam:'',
pageParam:'',
url:'http://jsonplaceholder.typicode.com/posts/1',
api: {
read : 'http://jsonplaceholder.typicode.com/posts/1',
create: 'http://httpbin.org/post'},
headers: {'Content-Type': "application/json" },
reader: {
type: 'json',
//rootProperty:'issues'
},
writer: {
type: 'json'
}
In my view I am calling create function as:
var user = Ext.create('posts', {"userId": 124,"title": "sunt","body": "quia"});
user.save();
As I am testing everything on http://jsonplaceholder.typicode.com/ so I am expecting that code will work cause when I test GET and POST functionality via Postman utility everything works fine.
Can anyone point out my error?
I found my mistake.
In the following code I was not setting the correct name of my model, as it won't be "Posts"
var user = Ext.create('posts', {"userId": 124,"title": "sunt","body": "quia"});
user.save();
Also if you are trying with http://jsonplaceholder.typicode.com/ you are not supposed to send ID in the post request.