Is there any documentation on use of [Restrict] attribute with service stack?
Not finding any documentation, I started trying to figure this out. I discovered you have to enable restrictions in AppHost.cs Configure event with
var endpointHostConfig = new EndpointHostConfig
{
EnableAccessRestrictions = true,
};
Then I added attributes to my request DTO:
[Route("Hello/World", "GET")]
[Restrict(EndpointAttributes.InternalNetworkAccess)]
This does not work...looks like that removes all 'default' restrictions and replaces it with just that one restriction? Using this instead seems to work:
[Restrict(InternalOnly = true)]
When I do a GET from the local lan it works, but from remote it does not. Interesting, the 'detailed stack error' it gives from remote is:
The following restrictions were not met: '\n -[InternalNetworkAccess, Secure, HttpHead, HttpPost, HttpPut, HttpDelete,
HttpOther, OneWay, Soap11, Soap12, Xml, Jsv, ProtoBuf, Csv, Html, Yaml, MsgPack, FormatOther, AnyEndpoint]'
Note, it does not even list HttpGet as one of the possiblities - which does work. Also mentions Secure and not InSecure...neither of which I am specifically requiring.
Can we get some clarification on exactly how this is supposed to work? What if I wanted to require SSL - how would I specify that?
What if I wanted to require SSL in production, but not staging on all services for this endpoint? (Realizing this may be a completely different way to configure).
The [Restrict] attribute feature is in the latest version of ServiceStack. Currently the only documentation for this exists in the Security wiki page.
Here are some EndpointAttributes restrictions tests that test the validation of the restriction attributes, and some different service configurations you can use.
The way it works is that it's restricted to anything that's specified, so if you want to enable SSL and leave everything else as unrestricted, you would only add:
[Restrict(EndpointAttributes.Secure)]
public class SslOnly { }
It also supports specifying multiple combinations of environments that are allowed, e.g. You can enforce HTTP internally, but HTTPS externally with:
[Restrict(EndpointAttributes.Secure | EndpointAttributes.External,
EndpointAttributes.InSecure | EndpointAttributes.InternalNetworkAccess)]
public class SslExternalAndInsecureInternal { }
Note: each environment is combined with Enum flags and delimited with a ,.
But it doesn't let you distinguish between debug and release builds, to enable this you would need to use C# conditional compilation symbols.
E.g only allow HTTP for Debug builds and HTTPS for production Release builds:
#if DEBUG
[Restrict(EndpointAttributes.InSecure)]
#else
[Restrict(EndpointAttributes.Secure)]
#endif
public class MyRequestDto { ... }
Related
I have created a Liferay 7 module, and it works well.
Problem: In the Java source code I hard-coded something that administrators need to modify.
Question: What is the Liferay way to externalize settings? I don't mind if the server has to be restarted, but of course the ability to modify settings on a live running server (via Gogo Shell?) could be cool provided that these settings then survive server restarts.
More specifically, I have a module for which I would like to be able to configure an API key that looks like "3g9828hf928rf98" and another module for which I would like to configure a list of allowed structures that looks like "BASIC-WEB-CONTENT","EVENTS","INVENTORY".
Liferay is utilizing the standard OSGi configuration. It's quite a task documenting it here, but it's well laid out in the documentation.
In short:
#Meta.OCD(id = "com.foo.bar.MyAppConfiguration")
public interface MyAppConfiguration {
#Meta.AD(
deflt = "blue",
required = false
)
public String favoriteColor();
#Meta.AD(
deflt = "red|green|blue",
required = false
)
public String[] validLanguages();
#Meta.AD(required = false)
public int itemsPerPage();
}
OCD stands for ObjectClassDefinition. It ties this configuration class/object to the configurable object through the id/pid.
AD is for AttributeDefinition and provides some hints for the configuration interface, which is auto-generated with the help of this meta type.
And when you don't like the appearance of the autogenerated UI, you "only" have to add localization keys for the labels that you see on screen (standard Liferay translation).
You'll find a lot more details on OSGi configuration for example on enroute, though the examples I found are always a bit more complex than just going after the configuration.
Service stack documentation explains that templates for meta and operation pages may be overridden using static files.
https://github.com/ServiceStack/ServiceStack/wiki/Virtual-file-system
This works well, however, I would prefer to deploy all my resources as embedded resources.
My assumption was that by registering my EmbeddedResourceSources in the hostConfig, that they would take precedence over the existing service stack templates but that does not seem to be the case:
SetConfig(new HostConfig
{
EmbeddedResourceSources = {typeof(ApiUiResource).Assembly},
EmbeddedResourceBaseTypes = {typeof(ApiUiResource)},
});
The above works to serve all my other files, but the default pages for the meta and operations pages are still shown. Is what I am attempting to do possible?
The Config.EmbeddedResourceBaseTypes contains the order by which the embedded resource virtual files are loaded, so you'll need add yours at the start of the list to take precedence:
var config = new HostConfig
{
EmbeddedResourceSources = {typeof(ApiUiResource).Assembly},
};
config.EmbeddedResourceBaseTypes.Insert(0,typeof(ApiUiResource));
SetConfig(config);
An alternative solution is to override GetVirtualFileSources() in your AppHost to change the order which the virtual file sources are returned, see the docs for an example of this.
The following code is snipped from the examples at docs.asp.net.
public void ConfigureServices(IServiceCollection services)
{
// Setup options with DI
services.AddOptions();
// Configure MyOptions using config
services.Configure<MyOptions>(Configuration);
// Configure MyOptions using code
services.Configure<MyOptions>(myOptions =>
{
myOptions.Option1 = "value1_from_action";
});
The call to services.Configure<MyOptions>(Configuration);
causes a compilation error:
cannot convert from 'Microsoft.Extensions.Configuration.IConfigurationRoot' to 'System.Action'
Manually setting up the options works fine. Am I missing something really obvious here?
I had the same problem and I found out you need to add this extension to your project :
Microsoft.Extensions.Options.ConfigurationExtensions
You need to add the following nuget package to your ASP Core Project if you want to configure the strongly typed config in that way.
Microsoft.Extensions.Options.ConfigurationExtensions
The extension methods contained in the package will allow you to configure the strongly typed configuration the way you want to and the way most tutorials show.
services.Configure<MyOptions>(Configuration);
Alternatively, you could add another binder package:
Microsoft.Extensions.Configuration.Binder
Configuration would then look something like this:
services.AddOptions();
services.Configure<MyOptions>(x => Configuration.Bind(x));
This is the downside of having so many modular packaged up extensions. It gets easy to lose track of where functionality exists.
I am working on a new API where we have requirement for many to many versioning.
Old Client -> New Server
Old Server -> New client
and everything in
between
I've read some of the other posts about defensive programming and having DTOs that evolve gracefully... and we are definitely going to use that pattern in most cases.
However, when we have a breaking change for CreateCustomer and require CreateCustomer2 DTO, I would like to be able to customize the way SS resolves the type that is used to deserialize, otherwise we will be forced to use routes like this:
/api/v1/createcustomer
/api/v2/createcustomer
Where I would much rather keep it /api/createcustomer and let the version number live in the Header / Querystring / whatever (not looking for a debate here :) ).
Are there any examples of how to resolve the deserialization type dynamically in ServiceStack, based on a parameter other than route + verb?
Many thanks in advance
The recommended approach for versioning is to take advantage for the natural forwards compatibility of message-based services and extend existing services defensively so it can support multiple client versions and avoid create multiple versions of the same service.
If you still want to expose /api/v1 routes than I'd recommend doing it at the infrastructure level by using a reverse proxy to re-route /api/v1 and /api/v2 requests to different running instances of ServiceStack.
If you want to do the proxying in code you can use base.ResolveService<T>() or base.ExecuteRequest() to execute different Services in code and ServiceStack's built-in AutoMapping to populate different DTO's which could look something like:
[Route("/customers")]
public class CreateCustomers {
public int Version { get; set; }
}
public class CreateCustomersV1 { ... }
public class CreateCustomersV2 { ... }
public class CustomerServices : Service
{
public object Any(CreateCustomers request)
{
return request.Version == 1
? base.ExecuteRequest(request.ConvertTo<CreateCustomersV1>())
: base.ExecuteRequest(request.ConvertTo<CreateCustomersV2>())
}
}
My public web app has a special servlet to generate a digest of published documents and saves them to a configured file path on server. This servlet must only be available by ip's specified by administrator of the app.
My hope is/was that this kind of stuff could be configured via tomcats security manager (a special servlet/ url should only be "listen" to a specific ip-(range)). Is this possible?
Or in general: i don't want to implement "security" in my code (the servlet it self could filter the ip). it should be a matter of container configuration or system configuration.
so how to achieve that
Tomcat already comes with Remote Address Filter valve that filters all requests to match a pattern. If you only need to provide filtering for a single URI, it is probably best to extend RequestFilterValve class and embed the logic in the extension. Something like this should work (haven't tested locally but you should be able to get the idea):
public class YourValve extends org.apache.catalina.valves.RequestFilterValve {
public void invoke(Request request, Response response) throws IOException, ServletException {
if (request.getRequestURI().startsWith("/path/to/your/secure/servlet") {
process(request.getRequest().getRemoteAddr(), request, response);
} else {
// no need to filter anything
}
}
}
You would have to configure this valve to provide allow regex, as explained in Remote Address Filter documentation. It could be something like
<Valve className="YourValve" allow="127\.\d+\.\d+\.\d+"/>
(above only allows localhost)
This article, chapter 4.1 explains how to install valves.