Istio configuration for websites with static content (in particular kubevious UI) - reverse-proxy

I'm trying to configure istio VirtualService so that I can open the kubevious dashboard (https://github.com/kubevious/kubevious) through it.
I have the following setup:
resource "kubernetes_manifest" "kubevious" {
provider = kubernetes-alpha
manifest = {
apiVersion = "networking.istio.io/v1alpha3"
kind = "VirtualService"
metadata = {
name = "kubevious"
namespace = "kubevious"
}
spec = {
gateways = [
"istio-system/space-gateway"
]
hosts = [
"*"
]
http = [
{
match = [
{
uri = {
prefix = "/kubevious"
}
}
]
rewrite = {
uri = "/"
}
route = [
{
destination = {
host = "kubevious-ui-svc.kubevious.svc.cluster.local"
}
}
]
},
{
match = [
{
uri = {
prefix = "/static"
}
},
{
uri = {
prefix = "/socket"
}
},
{
uri = {
regex: "^.*\\.(ico|png|jpg)$"
}
}
]
route = [
{
destination = {
host = "kubevious-ui-svc.kubevious.svc.cluster.local"
}
}
]
}
]
}
}
}
kubevious website is opening (albeit with some socket errors which I guess are related to kubevious).
I have one issue with this approach. What if I want to host more websites which have static content? Currently everything that goes to %istio_ingress_ip%/static will be forwarded to kubevious. Any other way to configure it so that i.e. when I invoke %istio_ingress_ip%/kubevious, it will resolve the static content to %istio_ingress_ip%/kubevious/static?

What if I want to host more websites which have static content?
AFAIK you should specify hosts for that, instead of *
For example let's say you have 2 static sites, example.com and sample.com, then you create 2 hosts in your virtual service.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: example-vs
spec:
hosts:
- example.com <----
http:
- match:
- uri:
prefix: /example
- uri:
prefix: /static
- uri:
prefix: /socket
- uri:
regex: "^.*\\.(ico|png|jpg)$"
route:
- destination:
host: example.default.svc.cluster.local
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: sample-vs
spec:
hosts:
- sample.com <----
http:
- match:
- uri:
prefix: /sample
- uri:
prefix: /static
- uri:
prefix: /socket
- uri:
regex: "^.*\\.(ico|png|jpg)$"
route:
- destination:
host: sample.default.svc.cluster.local
Additional resources:
https://medium.com/#MATT.LAW/istio-and-the-path-to-production-cdb260d58c85
Any other way to configure it so that i.e. when I invoke %istio_ingress_ip%/kubevious, it will resolve the static content to %istio_ingress_ip%/kubevious/static?
There are few resources worth to check about rewrite in istio.
istio: VirtualService rewrite to the root url
https://istio.io/latest/docs/reference/config/networking/virtual-service/#HTTPRewrite
https://discuss.istio.io/t/rewrite-url-to-the-root-in-the-gateway/2860/3

Related

Deploying Synapse Workspace with Managed Vnet Enabled (Bicep), but cannot assign private endpoints in UI

Situation:
I am deploying a Synapse workspace instance in Bicep with Managed Virtual Network Enabled.
I can see the Managed Vnet Is enabled from the UI:
However, when I enter the workspace my integration runtimes are not enabled for virtual network access and I cannot create managed private endpoints.
I'm writing the following code for the bicep deployment:
resource synapse_workspace 'Microsoft.Synapse/workspaces#2021-06-01' = {
name: synapse_workspace_name
location: location
tags: {
Workload: '####'
Environment: envName
Classification: 'Confidential'
Criticality: 'Low'
}
identity: {
type: 'SystemAssigned'
}
properties: {
// Git Repo
workspaceRepositoryConfiguration: {
accountName: '#####'
collaborationBranch: 'main'
projectName: '####'
repositoryName: '#############'
rootFolder: '/synapse/syn-data-${envName}'
tenantId: '####################'
type: 'WorkspaceVSTSConfiguration'
}
defaultDataLakeStorage: {
resourceId: storage_account_id
createManagedPrivateEndpoint: true
accountUrl: ###################
filesystem: ################
}
encryption: {
cmk: {
kekIdentity: {
useSystemAssignedIdentity: true
}
key: {
name: 'default'
keyVaultUrl: '#########################'
}
}
}
managedVirtualNetwork: 'default'
connectivityEndpoints: {
web: 'https://web.azuresynapse.net?workspace=%2fsubscriptions%######################
dev: 'https://##############.dev.azuresynapse.net'
sqlOnDemand: '################-ondemand.sql.azuresynapse.net'
sql: '################.sql.azuresynapse.net'
}
managedResourceGroupName: guid('synapseworkspace-managed-resource-group-${envName}')
sqlAdministratorLogin: 'sqladminuser'
privateEndpointConnections: []
managedVirtualNetworkSettings: {
preventDataExfiltration: true
allowedAadTenantIdsForLinking: []
}
publicNetworkAccess: 'Disabled'
cspWorkspaceAdminProperties: {
initialWorkspaceAdminObjectId: '#########################'
}
trustedServiceBypassEnabled: false
}
}
I get no errors in the deployment regarding the virtual network or any associated settings, but I still get the default integration runtime set to "Public" and not "Managed Virtual Network".
Is this a limitation in Bicep or am I missing some parameter?
Any help would be great
Joao

How can I configure Hardhat to connect to RSK Testnet?

To connect to an Ethereum Testnet,
the configuration in hardhat.config.js is like this:
networks: {
ropsten: {
url: `https://eth-ropsten.alchemyapi.io/v2/${ALCHEMY_API_KEY}`,
accounts: [`${ROPSTEN_PRIVATE_KEY}`]
}
}
(taken from here: https://hardhat.org/tutorial/deploying-to-a-live-network.html )
How can I add a network config for the RSK Testnet?
(Note that I'm using a seed phrase instead of a raw private key)
The network config in hardhat.config.js could be defined like so:
networks: {
rsktestnet: {
chainId: 31,
url: 'https://public-node.testnet.rsk.co/',
gasPrice: Math.floor(minimumGasPriceTestnet * TESTNET_GAS_MULT),
gasMultiplier: TESTNET_GAS_MULT,
accounts: {
mnemonic: mnemonic,
initialIndex: 0,
// if using RSK dPath
// Ref: https://developers.rsk.co/rsk/architecture/account-based/#derivation-path-info
path: "m/44'/37310'/0'/0",
// if using Ethereum dPath (e.g. for Metamask compatibility)
// path: "m/44'/60'/0'/0",
count: 10,
},
},
},
Where
mnemonic is your BIP-39 seed phrase.
TESTNET_GAS_MULT set to any value more than or equal to 1
minimumGasPriceTestnet see this answer or this answer

Enable diagnostic settings for Storage account using ARMTemplate

Storage account deployed from ARMTemplate is creating diagnostic settings as disabled.
How to enable diagnostics status using ARMTemplate or Powershell script?
Want to automate the process to deploy diagnostic settings.
Here is a solution using ARM templates in the newer Bicep format. In the example, it configures diagnostics settings for:
StorageAccount
Blob
File
Queue
Table
To reduce the template length, it configures only the StorageRead on the storage account services.
param name string
param location string = resourceGroup().location
param sku string
#description('Resource ID for the destination log analytics workspace.')
param logAnalyticsWorkspaceId string
resource storageAccount 'Microsoft.Storage/storageAccounts#2019-06-01' = {
name: name
location: location
kind: 'StorageV2'
sku: {
name: sku
}
properties: {
allowBlobPublicAccess: false
allowSharedKeyAccess: true
minimumTlsVersion: 'TLS1_2'
accessTier: 'Hot'
supportsHttpsTrafficOnly: true
networkAcls: {
defaultAction: 'Deny'
bypass: 'AzureServices'
}
}
}
resource diagnosticsStorage 'Microsoft.Insights/diagnosticSettings#2021-05-01-preview' = {
scope: storageAccount
name: 'diagnostics00'
properties: {
workspaceId: logAnalyticsWorkspaceId
metrics: [
{
category: 'Transaction'
enabled: true
}
]
}
}
resource blobService 'Microsoft.Storage/storageAccounts/blobServices#2021-06-01' = {
parent: storageAccount
name: 'default'
properties: {}
}
resource diagnosticsBlob 'Microsoft.Insights/diagnosticSettings#2021-05-01-preview' = {
scope: blobService
name: 'diagnostics00'
properties: {
workspaceId: logAnalyticsWorkspaceId
logs: [
{
category: 'StorageRead'
enabled: true
}
]
}
}
resource fileService 'Microsoft.Storage/storageAccounts/fileServices#2021-06-01' = {
parent: storageAccount
name: 'default'
properties: {}
}
resource diagnosticsFile 'Microsoft.Insights/diagnosticSettings#2021-05-01-preview' = {
scope: fileService
name: 'diagnostics00'
properties: {
workspaceId: logAnalyticsWorkspaceId
logs: [
{
category: 'StorageRead'
enabled: true
}
]
}
}
resource queueService 'Microsoft.Storage/storageAccounts/queueServices#2021-06-01' = {
parent: storageAccount
name: 'default'
properties: {}
}
resource diagnosticsQueue 'Microsoft.Insights/diagnosticSettings#2021-05-01-preview' = {
scope: queueService
name: 'diagnostics00'
properties: {
workspaceId: logAnalyticsWorkspaceId
logs: [
{
category: 'StorageRead'
enabled: true
}
]
}
}
resource tableService 'Microsoft.Storage/storageAccounts/tableServices#2021-06-01' = {
parent: storageAccount
name: 'default'
properties: {}
}
resource diagnosticsTable 'Microsoft.Insights/diagnosticSettings#2021-05-01-preview' = {
scope: tableService
name: 'diagnostics00'
properties: {
workspaceId: logAnalyticsWorkspaceId
logs: [
{
category: 'StorageRead'
enabled: true
}
]
}
}
Please follow the below URL to enable the Diagnostics Settings for Azure Storage Account using ARM Template:
https://learn.microsoft.com/en-us/azure/azure-monitor/essentials/resource-manager-diagnostic-settings#diagnostic-setting-for-azure-storage

There is no extension able to load the

I integrating of bundles FOSRestBundle,JMSSerializerBundle and NelmioApiDocBundle, I modified the files config.yml and routing.yml but I find this problem
code config.yml:
imports:
- { resource: parameters.yml }
- { resource: security.yml }
- { resource: services.yml }
- { resource: "#UserBundle/Resources/config/services.yml" }
# Put parameters here that don't need to change on each machine where the app is deployed
# http://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
locale: fr
framework:
#esi: ~
translator: ~
secret: "%secret%"
router:
resource: "%kernel.root_dir%/config/routing.yml"
strict_requirements: ~
form: ~
csrf_protection: ~
validation: { enable_annotations: true }
#serializer: { enable_annotations: true }
templating:
engines: ['twig']
default_locale: "%locale%"
trusted_hosts: ~
trusted_proxies: ~
session:
# handler_id set to null will use default session handler from php.ini
handler_id: ~
fragments: ~
http_method_override: true
# Twig Configuration
twig:
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"
# Doctrine Configuration
doctrine:
dbal:
driver: pdo_mysql
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
# if using pdo_sqlite as your database driver:
# 1. add the path in parameters.yml
# e.g. database_path: "%kernel.root_dir%/data/data.db3"
# 2. Uncomment database_path in parameters.yml.dist
# 3. Uncomment next line:
# path: "%database_path%"
orm:
auto_generate_proxy_classes: "%kernel.debug%"
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
# Swiftmailer Configuration
swiftmailer:
transport: "%mailer_transport%"
host: "%mailer_host%"
username: "%mailer_user%"
password: "%mailer_password%"
spool: { type: memory }
fos_user:
db_driver: orm # other valid values are 'mongodb', 'couchdb' and 'propel'
firewall_name: main
user_class: test\UserBundle\Entity\User
fos_rest:
view:
view_response_listener: 'force'
formats:
json: true
format_listener:
rules:
- { path: '^/api', priorities: ['json'], fallback_format: json, prefer_extension: true }
- { path: '^/', stop: true }
nelmio_cors:
paths:
'^/api/':
allow_credentials: true
allow_origin: ['*']
allow_headers: ['*']
allow_methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']
max_age: 3600
code routing.yml:
user:
resource: "#UserBundle/Resources/config/routing.yml"
prefix: /
med:
resource: "#MedBundle/Resources/config/routing.yml"
prefix: /
app:
resource: "#AppBundle/Controller/"
type: annotation
fos_user:
resource: "#FOSUserBundle/Resources/config/routing/all.xml"
NelmioApiDocBundle:
resource: "#NelmioApiDocBundle/Resources/config/routing.yml"
prefix: /api/doc
app_api:
resource: "#MedBundle/Resources/config/routing_rest.yml"
type: rest
prefix: /api
code routing_rest.yml:
api_app:
resource: MedBundle\Controller\Api\AppController
type: rest
code AppController.php:
<?php
namespace test\MedBundle\Controller\Api;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use FOS\RestBundle\Controller\Annotations\RouteResource;
/**
* #RouteResource("User")
*/
Class AppController extends Controller {
public function getAction() {
$em = $this->getDoctrine()->getManager();
$test = $em->getRepository('MedBundle:Apps')->findAll();
return array("test" => $test);
}
public function postAction(Request $request){
return $request->request->all();
}
}
Now I find this problem when it can test API
What is the solution and thank you
You don't have any configuration for assetic in your config.yml file. I assume you don't have the AsseticBundle installed on your app. Since Symfony 2.8, Assetic is no longer included by default in the Symfony Standard Edition. You need to install it yourself:
First require the bundle with composer:
composer require symfony/assetic-bundle
Enable the bundle in the AppKernel.php file
class AppKernel extends Kernel
{
// ...
public function registerBundles()
{
$bundles = array(
// ...
new Symfony\Bundle\AsseticBundle\AsseticBundle(),
);
// ...
}
}
add the following minimal configuration to your config.yml file to enable Assetic
# app/config/config.yml
assetic:
debug: '%kernel.debug%'
use_controller: '%kernel.debug%'
filters:
cssrewrite: ~

Swagger defination, how to specify that a file is returned?

I want to download a file from the server, and I define the swagger file as follows:
swagger: '2.0'
################################################################################
# API Information
################################################################################
info:
version: v0
title: XXX REST API
host: api.xxx.io
basePath: /v0
schemes:
- http
- https
produces:
- application/json
################################################################################
# Security
################################################################################
################################################################################
# Parameters
################################################################################
parameters:
productId:
name: productId
in: path
description: The product identifier
type: string
required: true
################################################################################
# Paths
################################################################################
paths:
/products:
get:
description: Get the list of products
operationId: getProducts
responses:
200:
description: OK
schema:
type: array
items:
$ref: '#/definitions/Product'
/resources/{productId}:
parameters:
- $ref: '#/parameters/productId'
get:
description: Get resources of a product
operationId: getResourcesByProductId
produces:
- application/octet-stream
responses:
200:
description: OK
schema:
type: file
################################################################################
# Definitions
################################################################################
definitions:
Product:
type: object
required:
- id
properties:
id:
type: string
name:
type: string
category:
type: array
items:
type: string
description:
type: string
price:
type: number
thumbnailUri:
type: string
previewUris:
type: array
items:
type: string
resources:
type: array
items:
$ref: '#ResourceMeta'
And the api is as follows:
#javax.annotation.Generated(value = "class io.swagger.codegen.languages.SpringCodegen", date = "2016-10-24T17:56:03.446+08:00")
#Controller
public class ResourcesApiController implements ResourcesApi {
public ResponseEntity<File> getResourcesByProductId(
#ApiParam(value = "The product identifier",required=true ) #PathVariable("productId") String productId
) {
// do some magic!
return new ResponseEntity<File>(HttpStatus.OK);
}
}
My controller is as follows:
#Controller
public class ResourceController implements ResourcesApi {
private final Logger logger = Logger.getLogger(ResourceController.class);
// #RequestMapping(value="/resources/{productId}", method= RequestMethod.GET)
public ResponseEntity<File> getResourcesByProductId(#ApiParam(value = "The product identifier", required = true) #PathVariable("productId") String productId) {
String path = "resources" + File.separator + productId;
File file = new File(path);
FileSystemResource fileSystemResource = new FileSystemResource(file);
InputStreamResource inputStreamResource = null;
try {
inputStreamResource = new InputStreamResource(fileSystemResource.getInputStream());
} catch (IOException e) {
logger.error(e.toString());
}
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition", String.format("attachment; filename=\"%s\"", file.getName()));
return ResponseEntity
.ok()
.headers(headers)
.contentLength(file.length())
.body(file);
}
}
However, when I run the application, it return a file but only contains the metadata of the file instead of its content. How can I make it return the file content? Thanks!
Use the InputStreamResource to return the file contents:
return new ResponseEntity(inputStreamResource, headers, HttpStatus.OK);